我有一个带有2个子视图的UIScrollView。我希望一个子视图是“前导对齐”(左对齐),其前缘与滚动视图的前缘对齐。我希望其他子视图为“尾对齐”(右对齐),其后缘与滚动视图的后缘对齐。
出于某种原因,autolayout意外地将第二个尾随对齐的子视图放在滚动视图的边界之外,到另一个子视图的前(左)侧,这样子视图的后边缘与前端的前沿对齐滚动视图。
我正在尝试以编程方式执行此操作。代码如下。我为2个子视图使用了2个标签。 “alpha”标签是正确的前导对齐,但“beta”标签不是应该是尾随对齐。
如果我尝试使用左对齐和右对齐而不是前导和尾随,也会发生这种情况。右对齐标签显示在与尾部对齐标签相同的错误位置。
我在这里和其他地方多次阅读iOS 6发行说明和答案,我只是不确定为什么会发生这种情况。
在视图控制器中:
- (void) viewDidLoad
{
[super viewDidLoad];
// Create and configure the scroll view.
UIScrollView * scrollView = [[UIScrollView alloc] init];
[scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
// For debugging.
[scrollView setClipsToBounds:NO];
scrollView.layer.borderColor = [UIColor redColor].CGColor;
scrollView.layer.borderWidth = 1.0;
[[self view] addSubview:scrollView];
// Layout scrollview.
// Horizontal: leading edge to superview's leading edge, with indent.
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:20.0]];
// Horizontal: trailing edge to superview's trailing edge, with indent.
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:-20.0]];
// Vertical: top edge to superview's top edge, with indent.
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:20.0]];
// Vertical: bottom edge to superview's bottom edge, with indent.
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:-20.0]];
// Create and configure first label which should be leading-aligned with scrollview.
UILabel * labelAlpha = [[UILabel alloc] init];
[labelAlpha setTranslatesAutoresizingMaskIntoConstraints:NO];
[labelAlpha setText:@"Alpha"];
[scrollView addSubview:labelAlpha];
// Layout first label.
// Horizontal: leading edge to scrollview's leading edge.
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelAlpha
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:scrollView
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0.0]];
// Vertical: top edge to scrollview's top edge.
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelAlpha
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:scrollView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0]];
// Create and configure second label which should be trailing-aligned with scrollview.
UILabel * labelBeta = [[UILabel alloc] init];
[labelBeta setTranslatesAutoresizingMaskIntoConstraints:NO];
[labelBeta setText:@"Beta"];
[scrollView addSubview:labelBeta];
// Layout second label.
// Horizontal: trailing edge to scrollview's trailing edge.
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelBeta
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:scrollView
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:0.0]];
// Vertical: top edge to scrollview's top edge.
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelBeta
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:scrollView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0]];
}
作为参考,视图控制器视图的recursiveDescription的输出会备份错位:
2013-07-15 22:04:23.892 Middleman[5669:907] <UIView: 0x20872960; frame = (0 0; 320 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = RM+BM; layer = <CALayer: 0x20871e60>>
| <UIScrollView: 0x208718a0; frame = (20 20; 440 280); gestureRecognizers = <NSArray: 0x20871f20>; layer = <CALayer: 0x208728e0>; contentOffset: {0, 0}>
| | <UILabel: 0x20872ab0; frame = (0 0; 44 21); text = 'Alpha'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x20872b90>>
| | <UILabel: 0x208730e0; frame = (-36 0; 36 21); text = 'Beta'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x20873170>>
答案 0 :(得分:6)
我努力解决同样的问题,最后找到了解决方案。请注意,我没有使用目标C,我使用的是MonoTouch(C#),但原理应该是相同的。
问题是AutoLayout解决UIScrollView约束的方式。对于许多其他视图,autolayout使用视图的对齐rect,在许多情况下,它与视图的框架重合。但是,在UIScrollView中,如果约束居中(例如,centerX),它似乎使用框架的大小(例如,宽度),这就是为什么我的子视图通常在UIScrollView中居中,但是当添加约束来右对齐时subview它使用contentSize宽度/高度。问题是在我的情况下contentSize宽度为0(仅垂直滚动),因此右对齐只意味着对齐0宽度框,这就是为什么我在左边看到我的子视图。
通常情况下,我也会通过约束解析contentSize,但在这种情况下,由于我是垂直滚动,因此只有高度contentSize不为零。我尝试在滚动视图中添加约束以便正确设置contentSize宽度,但我能做到这一点的唯一方法(同时保持页面的必要约束)是执行以下操作:
现在,我的UIScrollView的contentSize宽度已正确设置,并且事物按预期与其右边缘对齐。
答案 1 :(得分:1)
我的解决方法是在UIScrollView中插入某种helperView(例如UIView,UITableView)并对helperView应用6个约束:
- equal width to scrollView
- equal height to scrollView
- 0 leading space to scrollView
- 0 trailing space to scrollView
- 0 top space to scrollView
- 0 bottom space to scrollView
您可以将其他scrollView的子视图与helperView边缘对齐。
答案 2 :(得分:0)
您可以尝试使用文本的右对齐方式,也可以设置标签的宽度约束。否则标签大小适合内容。
CGFloat width = CGRectGetWidth(self.view.frame)-40.0;
labelBeta.preferredMaxLayoutWidth = width; //required for multi line wrapping
[scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[labelBeta(width)]|"
options:0 metrics:@{@"width":@(width)}
views:NSDictionaryOfVariableBindings(labelBeta)]];