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

时间:2014-02-06 23:18:41

标签: ios ios7 uiscrollview autolayout nslayoutconstraint

我以编程方式构建视图并使用autolayout,根本没有界面构建器。在自定义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],

}

Screenshot of problem

如您所见,绿色价格标签已正确对齐,但红色按钮远离屏幕左侧。 (我给了它5个像素的偏移量来显示它的位置。)那么,为什么scrollview的右侧实际上是左侧?如何正确对齐屏幕右侧?我哪里做错了?这让我发疯了!

感谢您的帮助!

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

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

2 个答案:

答案 0 :(得分:8)

约束的数量不是问题。 UILabelUIButton都将根据intrinsicContentSize确定其大小,因为您对该位置有约束,所以它应该具有布局所需的所有信息。

但是,当谈到自动布局时,UIScrollViews会以独特的方式运行。最佳描述来自此technical note。有两个选项可供选择,包括示例,但下面是每个选项的摘要。


混合方法

您只需向UIView添加UIScrollView,然后在UIView中添加和定位所有子视图。这需要您手动设置frame的{​​{1}}和UIView上的contentSize

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


纯自动布局方法

此选项使用您的自动布局约束来确定contentSize的{​​{1}}。这需要约束到UIScrollView的所有四个边缘,并且不能依赖于UIScrollView的大小。

此选项使用起来比较困难,因为您需要确保有足够的约束。在您的情况下,您将遇到问题,因为contentSize的顶部和底部没有约束,并且没有可用于确定UIScrollView宽度的约束。但是,当您必须处理动态内容时,此选项会很棒,因为它会根据需要调整UIScrollView的大小。


就个人而言,我会选择Pure Auto Layout Approach。它能够处理动态内容大小,使额外的约束设置值得。

如果你发布了你想要的最终版面,我会更新我的回答以反映这一点。


<强>更新

根据您发布的图像,这是我使用纯自动布局方法组织子视图的方式。主要区别在于UIScrollView现在是UIViewControllers视图的子视图。

contentSize

scrollView需要约束,因此它的边距是self.view的0px。

contentView需要约束,因此它的边距是scrollView的0px,宽度等于self.view。因此,当您旋转设备时,scrollView的UIScrollView会更新。

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

  • contentView top to imageView top
  • imageView height == some value
  • imageView底部标签顶部
  • 标签底部到contentView底部

答案 1 :(得分: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可能会按内容高度进行处理,但很可能会在控制台中发出警告。