【问题标题】:Resize UILabel to fit text inside custom UITableViewCell regardless of width调整 UILabel 的大小以适应自定义 UITableViewCell 中的文本,无论宽度如何
【发布时间】:2013-03-25 00:25:01
【问题描述】:

我试图让单元格中的标签大小合适,无论设备或方向如何。我能够正确调整行高。我还可以在cellForRowAtIndexPath 中正确设置标签高度,并且可以在我的日志中进行检查。但是,当它到达willDisplayRowAtIndexPath 时,标签高度已经改变,但只有当单元格不是 320 pts 宽时。

这是我的代码-

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"CustomCellIdentifier";
CustomInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
    cell = [[CustomInfoCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@"CustomInfoCell" owner:self options:nil];
    cell = objects[0];
}

// Configure the cell...
cell.customTitleLabel.text = [_data[indexPath.row] objectForKey:t];

CGFloat labelWidth = self.view.frame.size.width-40;
NSLog(@"labelWidth:%f",labelWidth);

NSString *text = [_data[indexPath.row] objectForKey:d];//correct text
CGSize labelsize=[text sizeWithFont:cell.customDetailLabel.font constrainedToSize:CGSizeMake(labelWidth, 2000.0) lineBreakMode:cell.customDetailLabel.lineBreakMode];
NSLog(@"labelsize:%f,%f",labelsize.width,labelsize.height);

//For testing
cell.customDetailLabel.backgroundColor = [UIColor redColor];
NSLog(@"Pre: %@",cell.customDetailLabel);
cell.customDetailLabel.frame=CGRectMake(20, 22, labelWidth, labelsize.height);

cell.customDetailLabel.text = text;
    NSLog(@"Post: %@",cell.customDetailLabel);
return cell;
}

willDisplayRowAtIndexPath 我也打印标签信息。这是一行打印的内容-

2013-03-24 18:33:44.009 Bridge Alert[57793:1e503] labelWidth:728.000000
2013-03-24 18:33:44.010 Bridge Alert[57793:1e503] labelsize:713.000000,76.000000
2013-03-24 18:33:44.010 Bridge Alert[57793:1e503] Pre: <UILabel: 0xad3eaf0; frame = (20 20; 280 21); text = 'Detail'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>>
2013-03-24 18:33:44.011 Bridge Alert[57793:1e503] Post: <UILabel: 0xad3eaf0; frame = (20 22; 728 76); text = 'Detail'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>>
2013-03-24 18:33:44.011 Bridge Alert[57793:1e503] Text set: <UILabel: 0xad3eaf0; frame = (20 22; 728 76); text = 'A bridge is considered “f...'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>>
2013-03-24 18:33:44.014 Bridge Alert[57793:1e503] Display:<UILabel: 0xad3eaf0; frame = (20 20; 728 190); text = 'A bridge is considered “f...'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>>

如您所见,通过 Display 调整标签的大小。我假设高度以某种方式重新计算,基于单元格是否为 320 pt 宽,这是内置的 UITableViewCell 宽度。

我怎样才能让标签的尺寸正确?

【问题讨论】:

  • 你试过取消选中自动布局吗?
  • 安吉洛,看来你是赢家了。将其发布为答案,我会仔细检查它是否适用于所有设备和方向。谢谢。
  • 很高兴我能帮上忙。 :)

标签: ios uitableview uilabel


【解决方案1】:

这就是使用 AutoLayout 以尽可能少的代码对我有用的方法。

在我的 ViewController 中,我添加了以下方法

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{        
    NSString * yourText = //place here the text you want to calculate its size;
    return 40 + [self heightForText:yourText];
}

-(CGFloat)heightForText:(NSString *)text
{
    NSInteger MAX_HEIGHT = 2000;
    UITextView * textView = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, 320, MAX_HEIGHT)];
    textView.text = text;
    textView.font = [UIFont boldSystemFontOfSize:12];
    [textView sizeToFit];
    return textView.frame.size.height;
}

上面的这段代码基本上会根据我的 UILabel 的大小 + 一个填充数(在我的例子中定义为 40)改变 UITableViewCell 的大小。

在此之后,我必须添加几个约束,如下所示,以使 UILabel 像 UITableViewCell 一样“拉伸”

运行后:

注意:我从 SO 中的许多线程中提取了不同的代码来提出这个解决方案。我希望我能记住这里提到的所有内容

希望对你们有用。

干杯

【讨论】:

  • 谢谢,效果很好(我只需要在左侧添加一个约束)
  • 漂亮的代码!你拯救了我的夜晚,我的朋友!
【解决方案2】:

您是否尝试过取消选中自动布局?这将消除不必要的(大多是无用的)约束。

【讨论】:

  • 在我看来,约束是 Apple 构建的最有用的开发人员工具之一……我强烈建议学习它们。
  • @mirkokiefer 在发帖时,我认为不需要自动布局。现在,是的。我总是使用自动布局。
【解决方案3】:

在我看来,界面构建器/故事板可能很有用,但通常会增加另一个不必要的复杂层。我将简单地将 UITableViewCell 子类化(就像您一样,但纯粹以编程方式进行)并使用 layoutSubviews 设置 customDetailLabel 的框架。

【讨论】:

    【解决方案4】:

    我曾经遇到过完全相同的问题,由于某种原因,标签高度在实际显示时会发生变化。我最终使用了免费的 Sensible TableView 框架,它实际上可以正确调整大小(如果您选择使用多行 UILabel,它甚至会调整单元格的大小)。该框架还自动从我的对象的属性中分配标签的文本,这真的很酷。

    【讨论】:

    • 谢谢-我希望不需要自定义框架来解决理论上应该很容易解决的问题,但它绝对看起来像一个方便的框架。
    • 我会尝试检查他们的源代码并为您提供所需的部分。
    • 看起来它们是预编译的,至少在免费版本中是这样的:-/
    【解决方案5】:

    尝试在您的CustomInfoCell 类中覆盖setFrame,以包括在设置框架后调整单元格中元素的大小。我已经包含了用于完成此操作的代码,这与您的实现略有不同。另外,在您的标签上,我将自动调整大小掩码设置为 UIViewAutoresizingFlexibleWidth

    在文件的顶部有这个:

    static void *kKVOContext;   // See: http://www.dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage/
    

    在 viewDidLoad 中包括:

    [self.textLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:&kKVOContext];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self
                   selector:@selector(orientationChanged:)
                       name:UIDeviceOrientationDidChangeNotification
                     object:[UIDevice currentDevice]];
    

    然后包括:

    - (void)setFrame:(CGRect)frame
    {
        [super setFrame:frame];
    
        //Resize elements to fit inside new frame
        [self textChanged];
    }
    
    - (CGSize)textLabelSize
    {
        BOOL portrait = UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
        CGFloat width = portrait ? [UIScreen mainScreen].bounds.size.width : [UIScreen mainScreen].bounds.size.height;
        CGFloat maxWidth = width - 90 - TEXT_X_LEFT_PADDING;
        CGSize maximumLabelSize = CGSizeMake(maxWidth, 10000);
    
        return [self.textLabel.text sizeWithFont:self.textLabel.font
                                                   constrainedToSize:maximumLabelSize
                                                       lineBreakMode:self.textLabel.lineBreakMode];
    }
    - (CGFloat)cellHeight
    {
        CGSize expectedLabelSize = [self textLabelSize];
    
        return (self.titleLabel.frame.origin.y+self.titleLabel.frame.size.height) + expectedLabelSize.height;
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary *)change
                           context:(void *)context {
    
        if ([keyPath isEqual:@"text"] && object == self.textLabel) {
            [self textChanged];
        }
    
        if(context != &kKVOContext)
        {
            [super observeValueForKeyPath:keyPath
                                 ofObject:object
                                   change:change
                                  context:context];
        }
    }
    
    - (void)orientationChanged:(NSNotification *)note
    {
        //Resize text on orientation change
        [self textChanged];
    }
    
    - (void)textChanged
    {
        CGRect newFrame = self.textLabel.frame;
        newFrame.size = [self textLabelSize];
    
        if(!CGRectEqualToRect(self.textLabel.frame, newFrame))
        {
            self.textLabel.frame = newFrame;
        }
    }
    

    【讨论】:

      【解决方案6】:

      只需发布我自己基于@Paulo 的简化方法,但现在适应故事板约束宽度和更准确。

      (斯威夫特)

      override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
          let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier")!
      
          // Use subclass of UITableViewCell if your cell is complex.
          let label = cell.viewWithTag(3001) as! UILabel;
          label.text = someStringArray[indexPath.row]
          label.sizeToFit();
      
          let y = label.frame.origin.y
          let height = label.frame.size.height
          let paddingBottom: CGFloat = 8
          // add other controls/view height if any after the expand label
      
          return y + height + paddingBottom
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多