iOS 7自动布局 - 无法将子视图的右侧与UIScrollView的右侧对齐

10

我正在以编程方式构建一个视图,并使用自动布局,完全不使用界面生成器。在自定义的ScrollView控制器中,我添加了一个UILabel和一个UIButton作为子视图。我想将该标签对齐到屏幕左侧,将按钮对齐到屏幕右侧。由于某种原因,我的按钮仅与我的滚动视图左侧对齐。我已经削减了代码,只保留了这两个标签,但我无法理解为什么它不会对齐到右侧。

HWScrollViewController.m(我如何初始化主滚动视图)

- (void)loadView
{
    self.scrollView = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

    self.scrollView.delegate = self;

    self.view = self.scrollView;
}

HWListingDetailViewController.m

- (void)viewDidLoad
{
[super viewDidLoad];

UILabel *priceLabel = [[UILabel alloc] init];
UIButton *favouriteButton = [UIButton buttonWithType:UIButtonTypeContactAdd];

[priceLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[favouriteButton setTranslatesAutoresizingMaskIntoConstraints:NO];

[priceLabel setText:@"$125.00"];
[favouriteButton setTitle:@"Add to Favourites" forState:UIControlStateNormal];

[self.view addSubview:priceLabel];
[self.view addSubview:favouriteButton];

[self.view addConstraints:@[
    [NSLayoutConstraint constraintWithItem:priceLabel 
                                 attribute:NSLayoutAttributeCenterY
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:self.view 
                                 attribute:NSLayoutAttributeCenterY 
                                multiplier:1 
                                  constant:0],

    [NSLayoutConstraint constraintWithItem:priceLabel 
                                 attribute:NSLayoutAttributeLeft 
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:self.view 
                                 attribute:NSLayoutAttributeLeft 
                                multiplier:1 
                                 constant:5],

    [NSLayoutConstraint constraintWithItem:favouriteButton 
                                 attribute:NSLayoutAttributeCenterY 
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:self.view 
                                 attribute:NSLayoutAttributeCenterY 
                                multiplier:1 
                                  constant:0],

    [NSLayoutConstraint constraintWithItem:favouriteButton 
                                 attribute:NSLayoutAttributeRight 
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:self.view 
                                 attribute:NSLayoutAttributeRight 
                                multiplier:1 
                                  constant:5],

如您所见,绿色价格标签对齐正确,但红色按钮偏离屏幕左侧太远。(我给它加了5像素的偏移量以显示它在哪里。) 那么为什么滚动视图的右边实际上是左边?如何正确地对齐到屏幕的右侧?我错在哪里了?这让我疯狂!

谢谢任何帮助!

最终布局图像: 我希望最终布局看起来像这样: 竖屏最终布局

如果旋转到横屏,我期望它看起来像这样: 横屏最终布局

2个回答

8
约束的数量不是问题。无论是UILabel还是UIButton,它们都会基于其intrinsicContentSize确定其大小,并且由于您已经对位置进行了约束,因此它应该拥有布局所需的所有信息。
然而,当涉及到自动布局时,UIScrollViews表现出独特的方式。最好的描述来自这个技术记录。包括示例在内有两个选项,但以下是每个选项的摘要。 混合方法 你只需要将一个UIView添加到UIScrollView中,然后在UIView中添加和定位所有子视图。这需要手动设置UIViewframeUIScrollView上的contentSize
这可能是使用您正在尝试实现的布局最容易的方法。但是,如果contentSize可以更改,则必须手动计算并更新该大小。 纯自动布局方法 此选项使用您的自动布局约束来确定UIScrollViewcontentSize。这需要到UIScrollView的所有四个边缘的约束,并且不能依赖于UIScrollView的大小。
此选项使用起来更加困难,因为您需要确保有足够的约束。在您的情况下,您将遇到问题,因为没有对UIScrollView的顶部和底部进行约束,并且没有可用于确定UIScrollView的宽度的约束。但是,当您必须处理动态内容时,此选项非常出色,因为它会根据需要调整contentSize的大小。
就我个人而言,我会选择纯自动布局方法。它处理动态内容大小的能力使额外的约束设置值得。
如果您发布您想要的最终布局,我将更新我的答案以反映该布局。 更新 基于您发布的图像,这是我使用纯自动布局方法组织子视图的方式。主要区别在于UIScrollView现在是UIViewControllers视图的一个子视图。
- UIView                                            (self.view)
  - UIScrollView                                    (scrollView)
    - UIView                                        (contentView)
      - UIImageView, UIButtons, UILabels, etc.

scrollView需要添加约束,使其边缘与self.view的距离为0px。

contentView需要添加约束,使其边缘与scrollView的距离为0px,并且宽度等于self.view。这是为了当您旋转设备时,scrollView的contentSize得以更新。

接下来,只需根据您想要的位置放置所有的图片和标签。标签需要被约束在左右两侧,以便计算其高度。值得注意的是,contentView将根据其子视图的约束来确定其高度,因此您需要"链接"contentView顶部和底部的约束。一个简单的例子如下:

  • contentView顶部约束到imageView顶部
  • imageView高度==某个值
  • imageView底部约束到label顶部
  • label底部约束到contentView底部

1
我同意纯自动布局方法是我所需要的,屏幕上会有相当数量的动态内容,但只会在垂直方向上动态变化。除了屏幕宽度之外,我真的没有任何设置水平约束的东西。我将编辑我的问题以添加最终布局图像。 - Wernzy

0

你的按钮没有足够的约束条件。实际上,你的标签也没有足够的约束条件,但这并不一定会阻止你的按钮对齐到屏幕右侧。

在水平和垂直方向上,你总是必须有指定视图行为的约束条件。通常这意味着至少四个约束条件 - x、y、宽度和高度。如果没有这些约束条件,iOS 将会为你猜测,很可能会出错。你可能会注意到 Xcode 控制台中会出现一些警告。

对于这个问题,解决方案取决于你想让你的视图看起来如何,但最简单的解决方案是为按钮设置一个宽度约束条件。你可以像这样做:

[NSLayoutConstraint constraintWithItem:favouriteButton 
                             attribute:NSLayoutAttributeWidth  
                             relatedBy:NSLayoutRelationEqual 
                             toItem:nil 
                             attribute:NSLayoutAttributeNotAnAttribute 
                             multiplier:1.0 
                             constant:64.0];

64.0f是按钮的宽度。

如果您希望按钮位于标签的右侧并共享相同的宽度(即每个占据屏幕的50%),可以这样做:

    [NSLayoutConstraint constraintWithItem:favouriteButton
                                 attribute:NSLayoutAttributeLeading
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:priceLabel
                                 attribute:NSLayoutAttributeTrailing
                                multiplier:1.0f
                                  constant:0.0f];

    [NSLayoutConstraint constraintWithItem:favouriteButton
                                 attribute:NSLayoutAttributeWidth
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:priceLabel
                                 attribute:NSLayoutAttributeWidth
                                multiplier:1.0f 
                                  constant:0.0f];

上述两个约束条件所做的就是将标签的尾缘设置为按钮的前缘,然后说这两个视图必须具有相同的宽度。

你还应该为两个视图添加高度约束(或顶部和底部约束)。我知道你已经有了垂直居中约束,但那并没有指定它的大小。iOS可能会通过内容高度来解决它,但很有可能会在控制台中出现警告。


1
不幸的是,这并没有解决问题。只要我不旋转视图,它就提供了一个相当接近的近似值,但如果我切换到横向模式,按钮就只是与标签左对齐。我对这个答案还有另一个问题,即如果没有UILabel,我仍然希望能够右对齐一个视图。 - Wernzy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接