AutoLayout多行UILabel剪掉一些文字
我试图学习汽车的布局,最终以为我发现这件事情时就挂上了。 我在玩原型单元和标签。 我正在尝试一个
- 标题,
titleLbl
– 图片中的蓝色框 - 钱,
moneyLbl
– 图片中的绿色框 - Subtitle / Description,
subTitleLbl
– 图片中的红色框
到目前为止,我有这样的:
我想要达到的是:
- 绿框应该始终显示在1行上
- 绿框内的值应该以蓝框为中心
- 蓝色框将会占用剩余的空间(在2之间为水平约束-8px),并且如果需要的话在多行上显示
- 红色框应该在下面,根据需要显示多行。
正如你所看到的,除了最后一行的例子之外,这几乎都是有效的。 我试图研究这个问题,从我能收集的内容来看,这与内在内容大小有关。 许多post在线推荐设置setPreferredMaxLayoutWidth
,我已经在多个地方为titleLbl
做了这个,并没有任何效果。 只有将其硬编码为180
时,才能得到结果,但是它还在文本上方/下方的其他蓝色框中添加了空白/填充,大大增加了红色/蓝色框之间的空间。
这是我的约束:
标题:
钱:
字幕:
基于我用其他文本样本运行的testing,它似乎使用了故事板中显示的宽度,但是任何尝试更正它都不起作用。
我已经创build了一个单元格的伊娃,并用它来创build单元格的高度:
- (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
:
- (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]; }
日志:
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
这是我所期望的,因为这两个元素之间有8px,控制台validation了这一点。 无论我将多less文本添加到蓝色框中(与故事板相同),它在第一行上都能完美地工作,但是对绿色框的任何增加都会抛出宽度计算。 我已经尝试在tableView:willDisplayCell
和tableView:heightForRowAtIndexPath:
设置这个以及其他问题的答案。 但不pipe它是不是布局。
任何帮助,想法或意见将不胜感激
阅读后find更好的答案: http : //johnszumski.com/blog/auto-layout-for-table-view-cells-with-dynamic-heights
创build一个UILabel
子类来覆盖layoutSubviews
如下所示:
- (void)layoutSubviews { [super layoutSubviews]; self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds); [super layoutSubviews]; }
这确保preferredMaxLayoutWidth
总是正确的。
更新:
经过多次发布的iOS和testing更多的用例我发现上述不足以满足每一个案件。 从iOS 8(我相信),在某些情况下,只有在屏幕加载之前调用didSet
bounds
。
在iOS 9中最近我遇到了另一个问题,当使用带有UITableView
的模态UIVIewController
时, layoutSubviews
和set bounds
都在 heightForRowAtIndexPath
之后被调用。 经过多次debugging,唯一的解决scheme是覆盖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 } }
我不知道我是否理解你,我的解决scheme与最好的解决scheme相去甚远,但这里是:
我在被切割的标签上添加了一个高度限制,将限制连接到单元格的出口。 我已经覆盖了layoutSubview方法:
- (void) layoutSubviews { [super layoutSubviews]; [self.badLabel setNeedsLayout]; [self.badLabel layoutIfNeeded]; self.badLabelHeightConstraint.constant = self.badLabel.intrinsicContentSize.height; }
和中提琴! 请尝试该方法并告诉我结果,谢谢。
Omg,只是有同样的问题。 @Simon McLoughlin的回答对我没有帮助。 但
titleLabel.adjustsFontSizeToFitWidth = true
做了一个魔术! 它的作品,我不知道为什么,但它确实。 是的,您的标签也必须具有明确的preferredMaxLayoutWidth值。
我花了一些时间来包装细胞,看起来像这样:
+--------------------------------------------------+ | This is my cell.contentView | | +------+ +-----------------+ +--------+ +------+ | | | | | multiline | | title2 | | | | | | img | +-----------------+ +--------+ | img | | | | | +-----------------+ +--------+ | | | | | | | title3 | | title4 | | | | | +------+ +-----------------+ +--------+ +------+ | | | +--------------------------------------------------+
经过多次尝试,我find了解决scheme,如何使用实际工作的原型单元。
主要的麻烦是我的标签可能会或可能不在那里。 每个元素都应该是可选的。
首先,我们的“原型”单元应该只在我们不处于“真实”环境时才进行布局。
因此,我创build了标志'heightCalculationInProgress'。
当有人(tableView的dataSource)要求计算高度时,我们正在使用block向原型单元格提供数据:然后我们要求我们的原型单元格布局内容并从中获取高度。 简单。
为了避免使用layoutSubviewrecursion的iOS7 bug,有一个“layoutingLock”variables
- (CGFloat)heightWithSetupBlock:(nonnull void (^)(__kindof UITableViewCell *_Nonnull cell))block { block(self); self.heightCalculationInProgress = YES; [self setNeedsLayout]; [self layoutIfNeeded]; self.layoutingLock = NO; self.heightCalculationInProgress = NO; CGFloat calculatedHeight = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; CGFloat height = roundf(MAX(calculatedHeight, [[self class] defaultHeight])); return height; }
外面的这个“块”可能是这样的:
[prototypeCell heightWithSetupBlock:^(__kindof UITableViewCell * _Nonnull cell) { @strongify(self); cell.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 0); cell.dataObject = dataObject; cell.multilineLabel.text = @"Long text"; // Include any data here }];
现在开始最有趣的部分。 布点:
- (void)layoutSubviews { if(self.layoutingLock){ return; } // We don't want to do this layouting things in 'real' cells if (self.heightCalculationInProgress) { // Because of: // Support for constraint-based layout (auto layout) // If nonzero, this is used when determining -intrinsicContentSize for multiline labels // We're actually resetting internal constraints here. And then we could reuse this cell with new data to layout it correctly _multilineLabel.preferredMaxLayoutWidth = 0.f; _title2Label.preferredMaxLayoutWidth = 0.f; _title3Label.preferredMaxLayoutWidth = 0.f; _title4Label.preferredMaxLayoutWidth = 0.f; } [super layoutSubviews]; // We don't want to do this layouting things in 'real' cells if (self.heightCalculationInProgress) { // Make sure the contentView does a layout pass here so that its subviews have their frames set, which we // need to use to set the preferredMaxLayoutWidth below. [self.contentView setNeedsLayout]; [self.contentView layoutIfNeeded]; // Set the preferredMaxLayoutWidth of the mutli-line bodyLabel based on the evaluated width of the label's frame, // as this will allow the text to wrap correctly, and as a result allow the label to take on the correct height. _multilineLabel.preferredMaxLayoutWidth = CGRectGetWidth(_multilineLabel.frame); _title2Label.preferredMaxLayoutWidth = CGRectGetWidth(_title2Label.frame); _title3Label.preferredMaxLayoutWidth = CGRectGetWidth(title3Label.frame); _title4Label.preferredMaxLayoutWidth = CGRectGetWidth(_title4Label.frame); } if (self.heightCalculationInProgress) { self.layoutingLock = YES; } }
- 如何在iOS的自动布局中设置视图的dynamic宽度和高度?
- 当我将UIPanGestureRecognizer和自动布局结合在一起时,我的UIViews变得糟糕透顶
- Autolayout在iOS 8上工作正常,但在iOS 6和7(我使用XCode 6.2)上performance不佳,
- 自动布局约束与dynamicvariables?
- 带有AutoLayout的UICollectionView Cell + UiLabel
- 将约束添加到xib中的“主视图”
- topLayoutGuide在子视图控制器中
- 如何将宽度等同于NSLayoutConstraint的某些UIViews?
- 表视图单元从View Controller返回到Table View Controller时“跳转”