【问题标题】:Sizing a UILabel to fit?调整 UILabel 的大小以适合?
【发布时间】:2009-01-02 07:00:37
【问题描述】:

如何修改 iPhone Developer's Cookbook 第 6 章中“09a - PrefsTable”配方中的以下 sn-p(在 tableView:cellForRowAtIndexPath: UITableViewController 方法中):

if (row == 1) { 
    // Create a big word-wrapped UILabel 
    cell = [tableView dequeueReusableCellWithIdentifier:@"libertyCell"]; 
    if (!cell) { 
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"libertyCell"] autorelease]; 
        [cell addSubview:[[UILabel alloc] initWithFrame:CGRectMake(20.0f, 10.0f, 280.0f, 330.0f)]]; 
    } 
    UILabel *sv = [[cell subviews] lastObject]; 
    sv.text =  @"When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation."; 
    sv.textAlignment = UITextAlignmentCenter; 
    sv.lineBreakMode = UILineBreakModeWordWrap; 
    sv.numberOfLines = 9999; 
    return cell; 
} 

...调整“sv”UILabel 子视图和“单元格”UITableViewCell 的大小,使其大小刚好适合文本(并使用或多或少的文本,以及其他类型的文本对齐方式)?我查看了 UILabel textRectForBounds:limitedToNumberOfLines: 方法,但文档指出它不应该直接调用(并且应该只被覆盖)。我尝试了 UIView sizeToFit 方法,但没有成功。

更新: I asked a new question about my problem with the NSString -sizeWithFont:forWidth:lineBreakMode: method.

【问题讨论】:

  • +1 表示选择的例句。

标签: cocoa-touch


【解决方案1】:

我必须这样做,以至于我扩展了 UILabel 来为我做这件事:

@interface UILabel (BPExtensions)
- (void)sizeToFitFixedWidth:(CGFloat)fixedWidth;
@end

@implementation UILabel (BPExtensions)


- (void)sizeToFitFixedWidth:(CGFloat)fixedWidth
{
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, fixedWidth, 0);
    self.lineBreakMode = NSLineBreakByWordWrapping;
    self.numberOfLines = 0;
    [self sizeToFit];
}
@end

然后让标签具有可变的多行高度但固定宽度:

[myLabel sizeToFitFixedWidth:kSomeFixedWidth];

【讨论】:

  • 魔术。将框架的高度设置为 0 - 然后调用 [self sizeToFit];谢谢。
  • 设置边界而不是框架不是更好吗?
  • Bounds 也可以,只是换帧而已。由于我将 x 和 y 设置为 self.frame.origin 值,它完成与 self.bounds = CGRectMake(0,0,fixedWidth,fixedHeight) 相同的事情,如果你可以设置 frame.size直接属性,但这不起作用:)
  • 谢谢,效果很好!虽然对于 ios 6 还有其他选择,但我的应用是 iOS 5+
  • 似乎 UILineBreakModeWordWrap 在 iOS 6 中已被弃用。 @OscarGomez 还有哪些其他选择?
【解决方案2】:

您应该使用 NSString 的 -sizeWithFont:forWidth:lineBreakMode: 方法来检索标签的相关尺寸指标。

【讨论】:

  • Kevin,如果您将答案更新为 -[NSString sizeWithFont:forWidth:lineBreakMode:] 我会接受。
  • 在swift中,你应该使用sizeWithAttributes方法
【解决方案3】:

另外,如果您要使用该代码,请将 numberOfLines 属性更改为 0

【讨论】:

    【解决方案4】:

    NSString-sizeWithFont:forWidth:lineBreakMode: 实际上并不执行自动换行。相反,请使用 -sizeWithFont:constrainedToSize:lineBreakMode: 获取字符串的准确宽度和高度值。

    【讨论】:

    • 刚刚看到您的其他问题的链接。看起来你在那里得到了它 - 对不起骗局。
    【解决方案5】:

    试试这个:

    sv.text =  @"When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation."; 
    sv.textAlignment = UITextAlignmentCenter; 
    sv.lineBreakMode = UILineBreakModeWordWrap; 
    sv.numberOfLines = 0;
    [sv sizeToFit]; 
    

    【讨论】:

      【解决方案6】:

      另外,你需要实现 UITableViewDelegate 方法:

      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
      

      并让它返回为调整大小的文本字段调整的总单元格高度。

      另一个注意事项 - 如果您如前所述将行数设置为 0,则“适合大小”实际上应该有效。它会返回一个尺寸,高度增加以适应标签中设置的自动换行文本,宽度设置为原始标签宽度。

      这对您没有帮助,因为您需要在获取单元格之前获取 heightForRow 的大小,因此您最好计算所需的高度(并且很可能缓存该计算,以免减慢表格渲染速度)

      【讨论】:

        【解决方案7】:

        这是我使用的一些代码:

        CGSize textSize = [myLabel.text sizeWithFont:myLabel.font];
        

        【讨论】:

          【解决方案8】:

          我遇到了类似的问题,我有一个 UITableViewCell,它在 StoryBoards 中设计为静态单元格。我用[super tableView:cellForRowAtIndexPath:] 得到它。所以我想调整 UILabel “detailTextLabel” 的大小,使其适合我设置的文本。风格是“正确的细节”。

          我只是在我的tableView:cellForRowAtIndexPath: 中设置了文本。和tableView:heightForRowAtIndexPath:相比,我回来了

          UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
          return cell.detailTextLabel.frame.size.height
          

          我的绳子很长。最后有一个宽单元格,标签中有 4 行文本。

          【讨论】:

            【解决方案9】:

            我有类似的问题。 我解决了这个问题。

            在 cellForRowAtIndexPath 方法中,将字体大小设置为您想要的任何值。

            cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
            cell.textLabel.numberOfLines = 0;    
            [cell.textLabel setFont:[UIFont systemFontOfSize:14.0]];
            [cell.textLabel sizeToFit];
            

            并在 heightForRowAtIndexPath 方法中增加字体大小。

                CGFloat height;
            
                UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
                NSString *text = cell.detailTextLabel.text;
                CGSize constraint = CGSizeMake(320, 20000.0f);
                CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:20.0]     constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
                CGFloat calHeight = MAX(size.height, 44.0f);
                height =  calHeight + (CELL_CONTENT_MARGIN * 2);
            
                return height;
            

            【讨论】: