AutoLayout 多行 UILabel 截断一些文本 [英] AutoLayout multiline UILabel cutting off some text

查看:21
本文介绍了AutoLayout 多行 UILabel 截断一些文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习自动布局,最后以为发生这种情况时我已经掌握了窍门.我正在玩原型单元格和标签.我正在尝试拥有一个

I'm trying to learn auto layout, finally thought I was getting the hang on it when this happened. I'm playing about with prototype cells and labels. I'm trying to have a

  • 标题,titleLbl - 图片中的蓝框
  • Money, moneyLbl - 图片中的绿框
  • 字幕/说明,subTitleLbl - 图片中的红框
  • Title, titleLbl - blue box in picture
  • Money, moneyLbl - green box in picture
  • Subtitle / Description, subTitleLbl - red box in picture

到目前为止,我有这个:

So far I have this:

我想要实现的是:

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

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

As you can see this is nearly all working, with the exception of the example in the last row. I've tried to research this and from what I can gather it is something to do with the intrinsic content size. Many posts online recommend setting setPreferredMaxLayoutWidth, i've done this in multiple places for the titleLbl and it has had no effect. Only when hardcoding it to 180 did I get the results, but it also added whitespace / padding to the other blue boxes on top / underneath the text, greatly increasing the space between the red / blue boxes.

这是我的限制:

标题:

金钱:

字幕:

根据我使用其他文本示例运行的测试,它似乎使用了故事板中显示的宽度,但任何纠正它的尝试都不起作用.

Based on tests i've run with other text samples it does appear to be using the width as shown in the storyboard, but any attempt to correct it isn't working.

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

I have created an ivar of the cell and used it to create the height of the cell:

- (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;
}

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

I've tried setting setPreferredMaxLayoutWidth inside the cell's layout subviews:

- (void)layoutSubviews
{
    [super layoutSubviews];

    NSLog(@"Money lbl: %@", NSStringFromCGRect(self.moneyLbl.frame));
    NSLog(@"prefferredMaxSize: %f 

", self.moneyLbl.frame.origin.x-8);

    [self.titleLbl setPreferredMaxLayoutWidth: self.moneyLbl.frame.origin.x-8];
}

日志:

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 

这是我所期望的,因为 2 个元素之间有 8px 并且控制台会验证这一点.无论我在蓝色框中添加多少文本,它都可以在第一行完美运行,这与情节提要相同,但是对绿色框的任何增加都会引发宽度计算.我已经尝试在 tableView:willDisplayCelltableView:heightForRowAtIndexPath: 以及其他问题的答案中进行设置.但无论如何它只是没有布局.

Which is what I would expect as there is 8px between the 2 elements and the console verifies this. It works perfectly on the first row no matter how much text I add to the blue box, which is the same as the storyboard, but any increase to the green box throws off the width calculation. I've tried setting this in the tableView:willDisplayCell and the tableView:heightForRowAtIndexPath: as well based on answers from other questions. But no matter what it just doesn't layout.

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

Any help, ideas or comments would be greatly appreciated

推荐答案

看完这篇文章找到了更好的答案:http://johnszumski.com/blog/auto-layout-for-table-view-cells-with-dynamic-heights

Found an even better answer after reading this: http://johnszumski.com/blog/auto-layout-for-table-view-cells-with-dynamic-heights

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

creating a UILabel subclass to override layoutSubviews like so:

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);

    [super layoutSubviews];
}

这可确保 preferredMaxLayoutWidth 始终正确.

This ensures the preferredMaxLayoutWidth is always correct.

更新:

在发布了多个 iOS 版本并测试了更多用例后,我发现上述内容不足以满足所有情况.从 iOS 8 开始(我相信),在某些情况下,只有在屏幕加载之前及时调用了 didSet bounds.

After several more release's of iOS and testing more usecase's i've found the above to not be sufficient for every case. As of iOS 8 (I believe), under some circumstances only didSet bounds was called in time before the screen load.

最近在 iOS 9 中,我在使用带有 UITableView 的模态 UIVIewController 时遇到了另一个问题,即 layoutSubviewsset bounds heightForRowAtIndexPath 之后被调用.经过大量调试后,唯一的解决方案是覆盖 set frame.

In iOS 9 very recently I came across another issue when using a modal UIVIewController with a UITableView, that both layoutSubviews and set bounds were being called after heightForRowAtIndexPath. After much debugging the only solution was to override set frame.

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

The below code now seems to be necessary to ensure it works across all iOS's, controllers, screen sizes etc.

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
    }
}

这篇关于AutoLayout 多行 UILabel 截断一些文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆