繁体   English   中英

UIView不遵守UIScrollView中的autolayout约束

[英]UIView not obeying autolayout constraints in UIScrollView

我将UIView添加到UIScrollView并对其进行约束,使其填充水平空间,除了一些边距。 我的视觉约束看起来像这样:

@"|-16-[theLineView]-16-|"

我已将视图设置为一个像素高,因此它将显示为一条线,并将其放在两个文本标签之间:

@"V:[someOtherStuff]-[aTextLabel]-[theLineView]-[anotherLabel]"

但是,我发现线条的宽度只扩展到它上面/下面最长标签的宽度。

为什么会这样?

PS我已阅读此http://developer.apple.com/library/ios/#technotes/tn2154/_index.html

在此输入图像描述

以下是来自测试项目的整个视图控制器代码,该测试项目在iPad上显示此问题。

- (void)viewDidLoad

{[super viewDidLoad];

self.scrollView = [[UIScrollView alloc] init];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
self.scrollView.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.scrollView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[scrollView]|"
                                                                 options:0
                                                                 metrics:0
                                                                   views:@{@"scrollView":self.scrollView}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                  options:0
                                                                  metrics:0
                                                                    views:@{@"scrollView":self.scrollView}]];

self.line1 = [[UIView alloc] init];
self.line2 = [[UIView alloc] init];
self.label1 = [[UILabel alloc] init];
self.label2 = [[UILabel alloc] init];
self.label3 = [[UILabel alloc] init];

for (UILabel *label in @[self.label1, self.label2, self.label3])
{
    label.text = @"I am a label and I am long enough that I can be multiline on an iphone but single on ipad";
}

for (UIView *view in @[self.line1, self.line2, self.label1, self.label2, self.label3])
{
    view.translatesAutoresizingMaskIntoConstraints = NO;
    view.backgroundColor = [UIColor redColor];
    [self.scrollView addSubview:view];
}

//horizontal layout - all views/labels should fill the horizontal space expect for margin
for (UIView *view in  @[self.line1, self.line2, self.label1, self.label2, self.label3])
{
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-16-[view]-16-|"
                                                                   options:0
                                                                   metrics:0
                                                                     views:@{@"view":view}];
    [self.scrollView addConstraints:constraints];
}

//vertical layout - stack em up
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[lab1]-[line1(==1)]-[lab2]-[line2(==1)]-[lab3]-|"
                                                                  options:0
                                                                  metrics:0
                                                                    views:@{@"lab1":self.label1, @"line1":self.line1, @"lab2":self.label2, @"line2":self.line2, @"lab3":self.label3}]];

}

UIScrollView会自动缩小以适应其中的视图。 你需要在某个地方设置宽度。

推荐策略:

  1. 使用约束(前导,尾随,顶部,底部)在其父视图内完全固定scrollview。
  2. 在UIScrollView中创建一个UIView,并将所需内容放入其中。
  3. 设置约束,以便UIView将充当内容视图(这意味着它足以包含所有元素)。 使用内在的内容大小,抗收缩性和元素的链接有很多约束。 生成的布局必须定义明确且唯一(这意味着如果要将所有约束移除到外部,布局仍然有效)。
  4. 连接UIView的边界与他们的superview(这是UIScrollView的实际内容视图,而不是UIScrollView!)。

如果在interface-builder中执行此操作(可能),则每次触摸该场景中的某些内容时都需要重新检查约束。 通过触摸我的意思是“选择”不仅“修改”。

找到了一个适用于您的用例的工作解决方案。 看到这里

扩大Patric Sc​​henke答案的第4位; 因为scrollView的内容大小是流动的,将内部视图固定到其边缘只是不能用于确定视图的宽度。 你的左侧引脚会工作,但两者都不会。 根据下一级容器计算视图宽度是可行的方法。 只要你的self.scrollView被固定到它的容器(我称之为containerView ),这行代码将完成你想要的。 将此行添加到for循环中以获得水平约束:

// Pin view's width to match the scrollView container's width
// -32 constant offset for margins
[containerView addConstraint:
  [NSLayoutConstraint constraintWithItem:view 
                               attribute:NSLayoutAttributeWidth
                               relatedBy:NSLayoutRelationEqual
                                  toItem:containerView
                               attribute:NSLayoutAttributeWidth
                              multiplier:1.0f
                                constant:-32]];

我找到了一种简单的基于约束的方法来实现这一点(我没有测试过这个解决方案的脆弱程度):

...@"H:|-16-[view]-16-|"... // (your original constraint)

[self.scrollView addConstraint:
  [NSLayoutConstraint constraintWithItem:view 
                               attribute:NSLayoutAttributeCenterX
                               relatedBy:NSLayoutRelationEqual
                                  toItem:self.scrollView
                               attribute:NSLayoutAttributeCenterX
                              multiplier:1.0f
                                constant:0.0f]];

这将view一直延伸到view的另一侧。 这可能不适合水平滚动的内容,但应垂直工作。

我意识到这是一年多以后的事了,但是对于单维滚动用例来说比patric.schenke的答案(这是好的和更强大的)更简单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM