【问题标题】:Auto Layout iOS 7 - Can't align right of subview to right of UIScrollView自动布局 iOS 7 - 无法将子视图的右侧对齐到 UIScrollView 的右侧
【发布时间】:2014-03-04 04:23:53
【问题描述】:

我正在以编程方式构建视图并使用自动布局,根本没有界面构建器。在自定义 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 个像素的偏移量来显示它的位置。)那么,为什么滚动视图的右侧实际上是左侧?如何正确对齐屏幕右侧?我哪里做错了?这快把我逼疯了!

感谢您的帮助!

最终布局图片: 我希望最终的布局是这样的:

如果旋转到横向,我希望它看起来像这样:

【问题讨论】:

    标签: ios ios7 uiscrollview autolayout nslayoutconstraint


    【解决方案1】:

    约束的数量不是问题。 UILabelUIButton 都将根据它们的 intrinsicContentSize 确定它们的大小,并且由于您对位置有限制,因此它应该具有布局所需的所有信息。

    但是,当涉及到自动布局时,UIScrollViews 的行为方式独特。最好的描述来自这个technical note。有两个选项可用,包括示例,但这里是每个选项的摘要。


    混合方法

    您只需将UIView 添加到UIScrollView,然后将所有子视图添加并定位在UIView 中。这需要您手动设置UIViewframeUIScrollView 上的contentSize

    这可能是您尝试实现的布局中最容易使用的。但是,如果contentSize 可以更改,则您必须手动计算和更新大小。


    纯自动布局方法

    此选项使用您的自动布局约束来确定contentSizeUIScrollView。这需要约束到 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。所以当你旋转设备时,滚动视图的contentSize 会更新。

    接下来只需按照您想要的方式放置所有图像和标签。标签需要左右约束,以便计算其高度。需要注意的重要一点是 contentView 将根据其子视图的约束来确定其高度,因此您将需要约束“链接” contentView 的顶部和底部。一个简单的示例如下所示。

    • contentView 顶部到 imageView 顶部
    • imageView 高度 == 一些值
    • imageView 底部到标签顶部
    • 标签底部到 contentView 底部

    【讨论】:

    • 我同意纯自动布局方法是我正在寻找的,屏幕上会有大量的动态内容,但是它只会在垂直方向上是动态的。除了屏幕的宽度,我真的没有任何东西可以设置水平约束。我将编辑我的问题以添加最终布局图像。
    【解决方案2】:

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

    总是必须有约束来指定视图在水平和垂直方向上的行为方式。通常这意味着至少有四个约束——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 可能会通过内容高度来解决问题,但它可能会在控制台中抛出警告。

    【讨论】:

    • 不幸的是,这并不能解决问题。只要我根本不旋转视图,它就提供了一个相当接近的近似值,但是如果我更改为横向模式,则该按钮将与标签左对齐。我对这个答案的另一个问题是,如果那里没有 UILabel,我希望仍然能够右对齐视图。
    猜你喜欢
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 2020-02-21
    相关资源
    最近更新 更多