ibireme / YYText

Powerful text framework for iOS to display and edit rich text.
MIT License
8.85k stars 1.69k forks source link

YYLabel使用autolayout后intrinsicContentSize和UILabel的结果不一致的问题 #610

Open captain-black opened 7 years ago

captain-black commented 7 years ago

在UITableViewCell子类内使用了YYLabel并用autolayout约束, 利用self-sizing自动适应cell高度. 原实现使用UILabel时, self-sizing自适应算出的cell高度是正确并能多行显示. 但现在换成YYLabel后self-sizing效果出现偏差总是算出一行的高度而已. 通过跟踪YYLabel代码, 做些一些比较绕的处理才能实现与UILabel一致 约束如下, 这种情况, 在superview宽度之前, 根本不知道preferredMaxLayoutWidth该是多少的 UIView superview; superview = [self.bubbleImageView superview]; [self.bubbleImageView mas_remakeConstraints:^(MASConstraintMaker make) { make.left.equalTo(superview).offset(8); make.right.lessThanOrEqualTo(superview).offset(-8); make.top.equalTo(superview).offset(4); make.bottom.lessThanOrEqualTo(superview).offset(-4); }];

superview = [self.msgLabel superview];
[self.msgLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(self.bubbleImageView).offset(4);
    make.right.equalTo(self.bubbleImageView).offset(-4);
    make.top.equalTo(self.bubbleImageView).offset(4);
    make.bottom.lessThanOrEqualTo(self.bubbleImageView).offset(-4);
}];

然后, 用hook在intrinsicContentSize方法被UIKit调用前设置了一下preferredMaxLayoutWidth才行. typeof(self) wself = self; [self.msgLabel aspect_hookSelector:@selector(intrinsicContentSize) withOptions:AspectPositionBefore usingBlock:^CGSize() { typeof(wself) self = wself; self.msgLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.contentView.frame) - 4 2 - 8 2; return CGSizeZero; } error:nil];

也不知道UILabel是怎么处理的, 不设置preferredMaxLayoutWidth intrinsicContentSize方法也能正确返回

catjia1011 commented 7 years ago

Add the following into the subclass of your UITableViewCell:

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
    let originalWidth = self.frame.size.width
    self.frame.size.width = targetSize.width
    self.layoutIfNeeded()
    self.yyLabel.preferredMaxLayoutWidth = self.yyLabel.width // or use other methods to calculate this width instead of using the "change frame" hacking
    let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
    self.frame.size.width = originalWidth
    return size
}
z234009184 commented 1 year ago

Add the following into the subclass of your UITableViewCell:

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
    let originalWidth = self.frame.size.width
    self.frame.size.width = targetSize.width
    self.layoutIfNeeded()
    self.yyLabel.preferredMaxLayoutWidth = self.yyLabel.width // or use other methods to calculate this width instead of using the "change frame" hacking
    let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
    self.frame.size.width = originalWidth
    return size
}

It's work for me!