AutoLayout多行UILabel切断了一些文字

Sim*_*lin 29 objective-c uilabel ios uistoryboard autolayout

我正在尝试学习自动布局,最后我想在发生这种情况时我正在抓住它.我正在玩原型细胞和标签.我想要一个

  • 标题,titleLbl- 图片中的蓝框
  • 金钱,moneyLbl- 图片中的绿色框
  • 字幕/描述,subTitleLbl- 图中的红色框

到目前为止我有这个:

iphone截图

我想要实现的是:

  • 绿色框应始终显示在1行上
  • 绿色框内的值应基于蓝色框居中
  • 蓝色框将占用剩余空间(对于2之间的水平约束为-8px),并在必要时显示在多行上
  • 红色框应位于下方,并根据需要显示尽可能多的行.

正如您所看到的,除了最后一行中的示例之外,这几乎都可以正常工作.我试图对此进行研究,从我可以收集的内容来看,这与内在的内容大小有关.网上有很多帖子推荐设置setPreferredMaxLayoutWidth,我已经在多个地方做了这个titleLbl并且没有任何效果.只有在硬编码时才能180得到结果,但它还在文本顶部/下方的其他蓝色框中添加了空格/填充,大大增加了红色/蓝色框之间的空间.

这是我的约束:

标题: 标题限制

钱: 金钱限制

字幕: 字幕约束

基于我与其他文本样本一起运行的测试,它看起来确实使用了故事板中显示的宽度,但任何纠正它的尝试都不起作用.

我创建了一个单元格的ivar并用它来创建单元格的高度:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    [sizingCellTitleSubMoney.titleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"title"]];
    [sizingCellTitleSubMoney.subtitleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"subtitle"]];
    [sizingCellTitleSubMoney.moneyLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"cost"]];

    [sizingCellTitleSubMoney layoutIfNeeded];

    CGSize size = [sizingCellTitleSubMoney.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    return size.height+1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MATitleSubtitleMoneyTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifierTitleSubTitleMoney];

    if(!cell)
    {
        cell = [[MATitleSubtitleMoneyTableViewCell alloc] init];
    }


    cell.titleLbl.layer.borderColor = [UIColor blueColor].CGColor;
    cell.titleLbl.layer.borderWidth = 1;

    cell.subtitleLbl.layer.borderColor = [UIColor redColor].CGColor;
    cell.subtitleLbl.layer.borderWidth = 1;

    cell.moneyLbl.layer.borderColor = [UIColor greenColor].CGColor;
    cell.moneyLbl.layer.borderWidth = 1;


    [cell.titleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"title"]];
    [cell.subtitleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"subtitle"]];
    [cell.moneyLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"cost"]];

    return cell;
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试setPreferredMaxLayoutWidth在单元格的布局子视图中进行设置:

- (void)layoutSubviews
{
    [super layoutSubviews];

    NSLog(@"Money lbl: %@", NSStringFromCGRect(self.moneyLbl.frame));
    NSLog(@"prefferredMaxSize: %f \n\n", self.moneyLbl.frame.origin.x-8);

    [self.titleLbl setPreferredMaxLayoutWidth: self.moneyLbl.frame.origin.x-8];
}
Run Code Online (Sandbox Code Playgroud)

日志:

2014-04-30 21:37:32.475 AutoLayoutTestBed[652:60b] Money lbl: {{209, 20}, {91, 61}}
2014-04-30 21:37:32.475 AutoLayoutTestBed[652:60b] prefferredMaxSize: 201.000000 
Run Code Online (Sandbox Code Playgroud)

这是我所期望的,因为2个元素之间有8px,控制台验证了这一点.它完美的第一行上不管多少文字我添加到蓝色的盒子,里面是一样的故事板,但任何增加的绿色框抛出了宽度计算.我已经尝试根据其他问题的答案设置了这个tableView:willDisplayCell和它tableView:heightForRowAtIndexPath:.但不管它只是没有布局.

任何帮助,想法或意见将不胜感激

Sim*_*lin 27

阅读本文后,我们找到了一个更好的答案:http://johnszumski.com/blog/auto-layout-for-table-view-cells-with-dynamic-heights

创建一个UILabel子类来覆盖,layoutSubviews如下所示:

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);

    [super layoutSubviews];
}
Run Code Online (Sandbox Code Playgroud)

这确保了preferredMaxLayoutWidth始终正确.

更新:

经过几次iOS发布和测试更多用例之后,我发现上述内容对于每种情况都不够.从iOS 8开始(我相信),在某些情况下只didSet bounds在屏幕加载之前及时调用.

在iOS中9最近我遇到另一个问题,当使用一个模式来UIVIewControllerUITableView,既layoutSubviewsset bounds被调用 heightForRowAtIndexPath.经过多次调试后,唯一的解决方案是覆盖set frame.

以下代码现在似乎是必要的,以确保它适用于所有iOS,控制器,屏幕尺寸等.

override public func layoutSubviews()
{
    super.layoutSubviews()
    self.preferredMaxLayoutWidth = self.bounds.width
    super.layoutSubviews()
}

override public var bounds: CGRect
{
    didSet
    {
        self.preferredMaxLayoutWidth = self.bounds.width
    }
}

override public var frame: CGRect
{
    didSet
    {
        self.preferredMaxLayoutWidth = self.frame.width
    }
}
Run Code Online (Sandbox Code Playgroud)