如何以编程方式将UIView粘贴到它的superview右侧

时间:2015-10-01 16:17:37

标签: ios objective-c autolayout

我拼命想把我的一个UILabel贴在它的超级视图的右边缘,而标签的宽度是可变的(这是时间,所以事情变得越来越大,应该是向左扩展,这是在设置文本时使用标签内部的sizeToFit完成的。​​

到目前为止,我已经尝试了很多东西,但我最接近:

_elapsedTimeRightConstraint = [NSLayoutConstraint constraintWithItem:_elapsedTimeView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:-150];

标签初始设置为150px宽度。但是当我修改常数时,一切都会变成地狱。

_elapsedTimeRightConstraint.constant = (_elapsedTimeView.frame.size.width * -1);
[self layoutIfNeeded];

所以我的问题是,当子视图的宽度不断变化时,如何对齐视图的尾随边缘以及它的超视图(因此它会粘在右边)。我一直在项目的其他地方使用FLKAutoLayout,所以如果这个框架可以很容易地完成,那么基本的自动布局解决方案也会很棒!!!

3 个答案:

答案 0 :(得分:6)

首先,如果要以编程方式创建标签,请确保translatesAutoresizingMaskIntoConstraints设置为NO

您需要的第一个约束是" label.trailing = superview.trailing"。

[NSLayoutConstraint constraintWithItem:label 
                             attribute:NSLayoutAttributeTrailing
                             relatedBy:NSLayoutRelationEqual
                                toItem:superview
                             attribute:NSLayoutAttributeTrailing
                            multiplier:1.f
                              constant:0.f]

这将固定超视图右边缘标签的右边缘(从左到右语言)。

您现在需要Y位置的约束。

在我的测试中,我使用以下约束垂直居中标签:

[NSLayoutConstraint constraintWithItem:label 
                             attribute:NSLayoutAttributeCenterY
                             relatedBy:NSLayoutRelationEqual
                                toItem:superview
                             attribute:NSLayoutAttributeCenterY
                            multiplier:1.f
                              constant:0.f]

现在就来了!

每次更改标签上的文字时,都需要使用AutoLayout重新计算框架。

[superview setNeedsLayout];
[superview layoutIfNeeded];

AutoLayout将:

1)询问标签的新尺寸(根据其文字)。

2)调整标签的大小。

3)将标签的后缘固定到超视图的后缘。

进一步研究

UILabel的问题在于,当您使用AutoLayout并设置文本时,其intrinsicContentSize会发生变化,但它不会触发布局更新。

在不使用UILabel子类的情况下强制执行此操作的方法是使用Objective-C运行时。

@interface UILabel (AutoLayout)

- (void)swz_setText:(NSString*)text;

@end

@implementation UILabel (AutoLayout)

+ (void)load
{
  NSLog(@"Swizzling [UILabel setFont:]...");

  Method oldMethod = class_getInstanceMethod(self, @selector(setText:));
  Method newMethod = class_getInstanceMethod(self, @selector(swz_setText:));

  method_exchangeImplementations(oldMethod, newMethod);
}

- (void)swz_setText:(NSString*)text
{
   if (![text isEqualToString:self.text]) {
       [self setNeedsLayout];
   }
   [self swz_setText:text]; //This now points to "setText:" - not a mistake!
}

@end

在此类别中,我是" m"增强"如果文本发生变化,请致电setText:来实现setNeedsLayout

现在你只需要在superview上调用layoutIfNeeded来重新计算/重新标记标签框。

点击操场上的here(Swift 2.0 - Xcode 7),我已经测试了我的代码。

我希望这会有所帮助。

答案 1 :(得分:0)

你好这里有一些要实现你想要的东西:

  • 设置 NSLayoutConstraintTrailing 常量等于0 ,并且前导约束 NSLayoutAttributeLeading 将其设置为大于或等于你想要的价值。
  • 使用NSLayoutConstraintTrailing和NSLayoutAttributeLeading而不是左右来处理其他语言 我希望这有帮助

答案 2 :(得分:0)

[yourLabel sizeToFit];    
CGRect frame = yourLabel.frame;
frame.x = parentView.frame.size.width - yourLabel.frame.size.width;
yourLabel.frame = frame;

它完全忽略了使用自动布局功能的“最佳实践”,但如果你再也受不了了......应该可行。 ; - )