我正在尝试创建一个可重复使用的消息UIView
子类,根据其UILabel
内的文本调整其高度。这个答案说它无法完成。那是真的吗? iOS message cell width/height using auto layout
我的问题是UILabel CGFrame
的身高太大了。 (UILabel
具有绿色背景色。)
这是我的代码(顺便说一下,[autolayoutView]
将translatesAutoresizingMaskIntoConstraints
设置为NO
):
SSLStickyView *stickyView = [[SSLStickyView alloc] initWithText:@"Try keeping a steady beat to help me get past the notes! Press the bass drum to jump!"];
SSLStickyView.m
- (instancetype)initWithText:(NSString *)text
{
self = [super initWithFrame:CGRectZero];
if (self)
{
_stickyImageView = [UIImageView autoLayoutView];
_stickyImageView.backgroundColor = [UIColor blueColor];
_stickyImageView.image = [UIImage imageNamed:@"element_sticky"];
[self addSubview:_stickyImageView];
float padding = 5;
NSMutableAttributedString *attributedText =
[[NSMutableAttributedString alloc]
initWithString:text
attributes:@
{
NSFontAttributeName: [UIFont boldSystemFontOfSize:30],
NSForegroundColorAttributeName: [UIColor purpleColor]
}];
UILabel *textLabel = [UILabel autoLayoutView];
textLabel.preferredMaxLayoutWidth = 50;
textLabel.attributedText = attributedText;
textLabel.numberOfLines = 0; // unlimited number of lines
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.backgroundColor = [UIColor greenColor];
[_stickyImageView addSubview:textLabel];
NSLayoutConstraint *stickyWidthPin =
[NSLayoutConstraint constraintWithItem:_stickyImageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:textLabel
attribute:NSLayoutAttributeWidth
multiplier:1
constant:padding * 2];
NSLayoutConstraint *stickyHeightPin =
[NSLayoutConstraint constraintWithItem:_stickyImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:textLabel
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
NSLayoutConstraint *stickyTextLabelTop =
[NSLayoutConstraint constraintWithItem:_stickyImageView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:textLabel
attribute:NSLayoutAttributeTop
multiplier:1
constant:0];
NSLayoutConstraint *stickyTextLeftPin = [NSLayoutConstraint constraintWithItem:_stickyImageView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:textLabel
attribute:NSLayoutAttributeLeft
multiplier:1
constant:-padding * 2];
NSDictionary *views = NSDictionaryOfVariableBindings(_stickyImageView, textLabel);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_stickyImageView]" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_stickyImageView]" options:0 metrics:nil views:views]];
[self addConstraints:@[stickyWidthPin, stickyHeightPin, stickyTextLeftPin, stickyTextLabelTop]];
self.backgroundColor = [UIColor whiteColor];
}
return self;
}
答案 0 :(得分:1)
让您的超级视图了解其内容大小的变化,并相应地调整超视图的宽度和高度。由于可能不会立即明白如何执行此操作,因此我提供了一个UIView子类,它将根据其内容(UILabel)调整自身大小。
注意:仅向ReusableMessageView添加会影响其超级视图中位置的约束。 ReusableMessageView将根据消息调整其宽度/高度。
@interface ReusableMessageView : UIView
-(instancetype)initWithMessage:(NSString *)message preferredWidth:(CGFloat)width;
-(void)setMessage:(NSString *)message;
@end
@implementation ReusableMessageView {
UILabel *_label;
}
-(instancetype)initWithMessage:(NSString *)message preferredWidth:(CGFloat)width {
if (self = [super init]) {
self.translatesAutoresizingMaskIntoConstraints = NO;
//setup label
_label = [UILabel new];
_label.translatesAutoresizingMaskIntoConstraints = NO;
_label.text = message;
_label.preferredMaxLayoutWidth = width;
_label.numberOfLines = 0;
[self addSubview:_label];
}
return self;
}
-(void)layoutSubviews {
[super layoutSubviews];
// remove all previously added constraints
[self removeConstraints:self.constraints];
CGFloat width = _label.bounds.size.width;
CGFloat height = _label.bounds.size.height;
NSLayoutConstraint *c1,*c2,*c3,*c4;
// set the view's width/height to be equal to the label's width/height
c1 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:width];
c2 = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:height];
// center the label
c3 = [NSLayoutConstraint constraintWithItem:_label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
c4 = [NSLayoutConstraint constraintWithItem:_label attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
// add all constraints
[self addConstraints:@[c1,c2,c3,c4]];
}
-(void)setMessage:(NSString *)message {
_label.text = message;
// once the message changes, the constraints need to be adjusted
[self setNeedsLayout];
}
@end
这可以通过重用现有约束并仅更改每个约束的“常量”属性来改进。如果你这样做,你甚至可以为变化添加动画。
以下是viewController的viewDidLoad方法中的示例用法:
ReusableMessageView *view = [[ReusableMessageView alloc]initWithMessage:@"This is the first message that is rather long in order to exaggerate the change in size" preferredWidth:50.0];
[self.view addSubview:view];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
// demonstrate the change in size
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[view setMessage:@"This is the second message"];
});
答案 1 :(得分:0)
当然可以做到,但不能没有代码。视图不会根据其内部的约束和大小自动使更小。这不是自动布局的行为方式。
您可以根据其中的内容的约束和大小(使用systemLayoutFittingSize
)确定某些内容的大小,您可以设置< / em>代码中那个大小的东西。但它不会通过某种魔法发生。