【问题标题】:AutoLayout to keep view sizes proportional自动布局以保持视图大小成比例
【发布时间】:2012-10-02 03:55:01
【问题描述】:

我正在努力实现以下目标:

  • 我的 xib 中有 2 个视图需要与边缘(两侧和顶部)保持 20 像素的距离
  • 需要调整大小的 2 个视图大小不同
  • 它们必须相距 20 像素
  • 它们的宽度需要保持相对于父视图的宽度

我阅读了一个关于这样做的教程,它可以工作,但问题是它要求两个视图具有相同的宽度和 pin Widths equally,这是我不想要的。

这是我尝试过的:

  • 向左视图添加前导空间约束为 20 像素
  • 向左视图添加顶部空间约束为 20 像素
  • 为右视图添加顶部空间约束为 20 像素
  • 将拖尾空间约束添加到右视图为 20 像素
  • 为两个视图添加水平间距约束为 20 像素

我遇到的问题是左视图没有调整大小,而右视图填充了空间以保持 20 像素的水平空间。

有没有办法让两个视图按比例调整它们应该填充的空间?

这是我的布局和约束的截图:

谢谢!

编辑

我在尝试旋转设备时收到以下警告:

2012-10-11 08:59:00.435 AutolayoutTest[35672:c07] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want.
    Try this: (1) look at each constraint and try to figure out which you don't expect;
    (2) find the code that added the unwanted constraint or constraints and fix it. (Note:  
    If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x8a6b2b0 H:[UIView:0x8a6b1d0(170)]>",
    "<NSLayoutConstraint:0x8a68ad0 H:[UIView:0x8a69430(90)]>",
    "<NSLayoutConstraint:0x8a6ba40 H:[UIView:0x8a69430]-(20)-[UIView:0x8a6b1d0]>",
    "<NSLayoutConstraint:0x8a6ba00 H:[UIView:0x8a6b1d0]-(20)-|   (Names: '|':UIView:0x8a6b7e0 )>",
    "<NSLayoutConstraint:0x8a6b940 H:|-(20)-[UIView:0x8a69430]   (Names: '|':UIView:0x8a6b7e0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x7199aa0 h=--& v=--& V:[UIView:0x8a6b7e0(568)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x8a6b2b0 H:[UIView:0x8a6b1d0(170)]>

【问题讨论】:

  • 我也有同样的问题。这应该不是那么难。使用自动调整大小的蒙版非常容易。
  • XCode 6 中的一些更改使这变得容易多了。您可以为任何相等的宽度/高度约束设置“乘数”字段。或者您可以使用“纵横比”约束来完成此操作。下面的许多答案(不是公认的)解释了这一点

标签: ios interface-builder ios6 autolayout nslayoutconstraint


【解决方案1】:

在 Interface Builder 中,使用右键拖动视图(稍微显示黑色弹出窗口)。
在弹出菜单中选择Aspect Ratio

【讨论】:

    【解决方案2】:

    只需选择宽高比:

    【讨论】:

    • 长宽比是什么?这如何解决问题?
    【解决方案3】:

    现在可以在 XCode 6 中使用宽高比属性

    【讨论】:

      【解决方案4】:

      我可能迟迟没有提出解决方案,但这实际上可以在 IB非常容易完成。

      首先,添加一个 UIView 并固定到超级视图的所有四个边缘。

      然后,添加您的 第一个子视图 并相应地定位它(例如:x = 0,y = 0,高度 = 固定高度,宽度 = 您希望相对于 UIView 的宽度 我们固定到所有四个边缘)。

      同时选择 UIView第一个子视图 并添加 Equal Widths 约束。当然,这会在自动布局中显示定位错误,但没关系,因为这(还)不是你想要的。

      现在技巧来了: 选择 Equal Widths 约束并编辑 Multiplier 为您想要的比例(例如:1:4如果您希望第一个子视图是 UIView 的 1/4)。 对第二个子视图和 Tadaaaaaa 重复步骤!

      【讨论】:

      • 如何以编程方式使用分数更改乘数?
      • @Jessica :乘数属性是只读的。您必须删除旧的 NSLayoutConstraint 并用新的替换它来修改它。这可能看起来很麻烦,但这是 Apple 的设计。你别无选择。对不起。
      • 如何将其应用于间距?我喜欢这个主意。 +1
      • @Jules : 你把它应用于间距是什么意思?
      • 固定到边缘,我想我可以为不同的常量值安装不同的布局。
      【解决方案5】:

      这可以通过再添加一个虚拟视图(dummyView)来解决,其约束设置为固定宽度、高度并与 Superview 的 centerX 对齐。然后添加左视图和右视图水平间距约束到虚拟视图

      【讨论】:

      • 我喜欢这个主意!让我试试看!
      • 那为什么不直接将两个view的边约束到superview的中心呢?
      • @DavideDeFranceschi 如果我们像您所说的那样,两个视图可能会相互折叠,因为缺少从左视图到右视图的尾随约束。
      • 不确定,每个视图将有 2 个独立的水平约束,因此它们将被很好地定义。当然,如果容器视图太小(以至于其中一个视图会导致负宽度)那么它将无法工作,但这不应该是研究案例中发生的事情
      【解决方案6】:

      正如其他人所提到的,关键是在“Pin Widths Equally”约束上设置一个乘数,以便视图宽度最终成为彼此的倍数。 XCode 5.1 应该添加在 Interface Builder 中设置它的功能,但在那之前,除了在代码中设置它之外,您还有另一个选择。如果您创建“Pin Widths Equally”约束,然后转到右侧 Utilities Panel 中的 Identity Inspector,然后查找“User Defined Runtime Attributes”。添加一个新属性,其键路径为“multiplier”,键入“number”,值等于您想要的比率。

      这不会反映在 Interface Builder 中,但会在使用您的视图时应用。

      【讨论】:

      • 正如您所说,Interface Builder (XCode 5.1) 包括 Equals Height 约束的乘数:) 接受这个答案! :)
      • 幸运的是,在 XCode 6 中,它们具有解决此问题的“纵横比”约束”
      【解决方案7】:
      1. 去掉代码中的两个宽度约束,或者在 IB 中降低它们的优先级,否则你会过度约束。
      2. 在代码中添加一个约束来描述绿色视图和蓝色视图之间的宽度比:

        // Assuming the ratio you want is green_view_width : blue_view_width = 1 : 2
        NSLayoutConstraint *c = [NSLayoutConstraint constraintWithItem:greenView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeWidth multiplier:0.5f constant:0.f];
        [commonSuperview addConstraint:c];
        

      【讨论】:

        【解决方案8】:

        我是自动布局的新手,但遇到了您的问题并认为这将是一个很好的挑战。 (这是我的警告,以防这不是理想的解决方案!)

        您需要在代码中添加宽度约束。我通过首先在没有宽度限制的 NIB 中添加两个视图来实现这一点。这些是第一个(左)视图的约束:

        这些是我对第二个(右)视图的限制:

        这会在第二个视图上留下您不想要的额外约束 - 超级视图和第二个视图之间的前导空间,如下所示:

        您不能在 IB 中删除该约束,因为它会留下不明确的布局(因为我们在子视图上没有宽度)。但是,您可以在代码中将其删除。首先,为它设置一个outlet并在IB中连接它:

        @property (nonatomic, strong) IBOutlet NSLayoutConstraint *view2superviewLeadingConstraint;
        

        然后,在您的视图控制器的 viewDidLoad 中,您可以使用以下方法将其删除:

        [self.view removeConstraint:self.view2superviewLeadingConstraint];
        

        最后,添加宽度约束。这里的关键是 multiplier 参数,用于指示您希望宽度基于超级视图宽度的百分比。另请注意,您必须将常量参数设置为等于 IB 中设置的前导/尾随总计:

        NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.3 constant:-20];
        [self.view addConstraint:constraint1];
        
        NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.view2 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.7 constant:-40];
        [self.view addConstraint:constraint2];
        

        【讨论】:

        • 您不需要直接删除约束。在 IB 中,一次选择一个“占位符”约束(单击 cog-down-arrow 并选择“Select and edit...”),然后选中“remove at build time”框。
        【解决方案9】:

        我不确定你对自动布局有多熟悉,如果这是你已经知道的内容,我们深表歉意:

        使用自动布局时,可以为同一个属性分配多个约束。在某些情况下,这些约束可能相互矛盾。这就是导致您看到的警告的原因。

        从您发布的屏幕截图中看起来,您已经设置了几个明确的约束 - 例如,左侧的绿色视图有一个约束,上面写着“宽度 (90)” ,这意味着宽度必须正好等于 90 点。

        仅从屏幕截图中还不清楚您的其他约束映射到什么,但这里可能发生的是这些显式约束导致问题 - 您有自动调整大小的约束,说视图应该扩展或收缩以适应其可用区域,但是那些相同的视图具有要求它们具有精确宽度的约束。

        这可以通过多种方式解决 - 您可以删除视图上的那些显式宽度约束,或者您可以更改它们的优先级(默认情况下约束是“必需的”,但您可以将它们更改为可选)。

        【讨论】:

        • 我尝试将这 2 个宽度约束设为可选,警告消失了,但一个视图调整大小而另一个视图不存在的问题。
        • 尝试使宽度限制“大于或等于”而不是“等于”。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-16
        • 2016-11-26
        • 2014-02-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-20
        • 2022-01-03
        相关资源
        最近更新 更多