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

Ond*_*rej 5 objective-c ios autolayout

我正在拼命地试图将我的一个UILabel粘贴到它的超视图的右边缘,而标签的宽度是可变的(这是一个时间,所以事情变得越来越大,应该向左扩展,这是使用标签内的sizeToFit完成的当设置文本时).

到目前为止,我已经尝试了大量的东西,但我最接近:

_elapsedTimeRightConstraint = [NSLayoutConstraint constraintWithItem:_elapsedTimeView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:-150];
Run Code Online (Sandbox Code Playgroud)

虽然标签最初设置为150px宽度.但是当我修改常量时,一切都会变成地狱.

_elapsedTimeRightConstraint.constant = (_elapsedTimeView.frame.size.width * -1);
[self layoutIfNeeded];
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*ini 6

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

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

[NSLayoutConstraint constraintWithItem:label 
                             attribute:NSLayoutAttributeTrailing
                             relatedBy:NSLayoutRelationEqual
                                toItem:superview
                             attribute:NSLayoutAttributeTrailing
                            multiplier:1.f
                              constant:0.f]
Run Code Online (Sandbox Code Playgroud)

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

您现在需要对该Y位置进行约束.

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

[NSLayoutConstraint constraintWithItem:label 
                             attribute:NSLayoutAttributeCenterY
                             relatedBy:NSLayoutRelationEqual
                                toItem:superview
                             attribute:NSLayoutAttributeCenterY
                            multiplier:1.f
                              constant:0.f]
Run Code Online (Sandbox Code Playgroud)

现在来了!

每次更改标签上的文本时,都需要使用AutoLayout重新计算帧.

[superview setNeedsLayout];
[superview layoutIfNeeded];
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

在这个类别中,我setText:通过调用setNeedsLayout文本更改来"增强" 实现.

现在,您只需要layoutIfNeeded在superview上调用以重新计算/重新标记标签框架.


点击这里查看操场(Swift 2.0 - Xcode 7),我测试了我的代码.

我希望这有帮助.