【问题标题】:Set up constraints which depends on the frame of the superview设置依赖于父视图框架的约束
【发布时间】:2015-07-27 10:20:15
【问题描述】:

我想设置一些宽度约束,这取决于超级视图的宽度。事实上,我想使用自动布局,但我需要访问 superviews 框架来计算我的子视图的宽度。我所有的子视图都添加到 UIView 而不是视图控制器。

我在构造函数中设置了约束,但我想在updateConstraints中更改它们。

构造函数:

nfloat initialWidth = (nfloat)Math.Round((Bounds.Size.Width / 7) - (nfloat)(Math.Ceiling(Bounds.Size.Width % 7) / 2));
container0WidthConstraint = NSLayoutConstraint.Create (container0, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, initialWidth);
container1WidthConstraint = NSLayoutConstraint.Create (container1, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, initialWidth);

AddConstraints (new NSLayoutConstraint[] { container0WidthConstraint, container1WidthConstraint });

updateConstraints:

public override void UpdateConstraints ()
{
    nfloat desiredItemWidth = (nfloat)Math.Round(Bounds.Size.Width / 7);
    nfloat remainingWidth = Bounds.Size.Width - desiredItemWidth * 5;

    if (remainingWidth % 2 == 0) {
        // even
        container0WidthConstraint.Constant = remainingWidth / 2;
        container1WidthConstraint.Constant = remainingWidth / 2;
    } else {
        // odd
        container0WidthConstraint.Constant = (nfloat)Math.Floor(remainingWidth / 2);
        container1WidthConstraint.Constant = (nfloat)Math.Ceiling(remainingWidth / 2);
        }

    base.UpdateConstraints ();
}

代码在 C# 中,但我仅将其添加为附加信息。基本上,我想将屏幕分成大小相等的视图。我发现唯一可行的方法是通过如上所示的计算。

我需要Bounds.Size.Width,但调试时它总是空的。设置后如何添加取决于超级视图框架的约束?

编辑:

我认为这对我不起作用的主要原因是它被添加为子视图,因此自动布局系统尚未完成。我应该在哪里放置layoutIfNeeded 还是应该使用layoutSubviews?尝试后一种时,我收到错误“执行 -layoutSubviews 后仍需要自动布局”。那么我应该在哪里放置我的约束或者我应该如何设置我的视图层次结构?

自动布局错误:

"<NSLayoutConstraint:0x7bd11540 H:|-(0)-[UIView:0x7bd16b90]   (Names: '|':TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0 )>",
    "<NSLayoutConstraint:0x7bd11660 H:[UIView:0x7bd16b90]-(0)-[UIView:0x7bd166a0]>",
    "<NSLayoutConstraint:0x7bd114f0 H:[UIView:0x7bd166a0]-(0)-[UIView:0x7bd16a10]>",
    "<NSLayoutConstraint:0x7bd114c0 H:[UIView:0x7bd16a10]-(0)-[UIView:0x7bd163f0]>",
    "<NSLayoutConstraint:0x7bd11490 H:[UIView:0x7bd163f0]-(0)-[UIView:0x7bd15f90]>",
    "<NSLayoutConstraint:0x7bd11460 H:[UIView:0x7bd15f90]-(0)-[UIView:0x7bd15d80]>",
    "<NSLayoutConstraint:0x7bd11410 H:[UIView:0x7bd15d80]-(0)-[UIView:0x7bd15ad0]>",
    "<NSLayoutConstraint:0x7bd113e0 H:[UIView:0x7bd15ad0]-(0)-|   (Names: '|':TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0 )>",
    "<NSLayoutConstraint:0x7bd115c0 UIView:0x7bd16b90.width == 0.142857*TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0.width>",
    "<NSLayoutConstraint:0x7bd11820 UIView:0x7bd166a0.width == 0.142857*TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0.width>",
    "<NSLayoutConstraint:0x7bd11850 UIView:0x7bd16a10.width == 0.142857*TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0.width>",
    "<NSLayoutConstraint:0x7bd11880 UIView:0x7bd163f0.width == 0.142857*TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0.width>",
    "<NSLayoutConstraint:0x7bd118b0 UIView:0x7bd15f90.width == 0.142857*TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0.width>",
    "<NSLayoutConstraint:0x7bd11270 UIView:0x7bd15d80.width == 0.142857*TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0.width>",
    "<NSLayoutConstraint:0x7bd11240 UIView:0x7bd15ad0.width == 0.142857*TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0.width>",
    "<NSLayoutConstraint:0x7b8d6d60 H:|-(0)-[TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0]   (Names: '|':UIView:0x7bc3e1e0 )>",
    "<NSLayoutConstraint:0x7b8ce180 H:[TestSevenEquallySpaced_SevenEquallySpacedViews:0x7bd255e0]-(0)-|   (Names: '|':UIView:0x7bc3e1e0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x7bd018b0 h=-&- v=-&- UIView:0x7bc3e1e0.height == UIWindow:0x7bc3e710.height>",
    "<NSAutoresizingMaskLayoutConstraint:0x7bd00ea0 h=--- v=--- V:[UIWindow:0x7bc3e710(1024)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7bd11410 H:[UIView:0x7bd15d80]-(0)-[UIView:0x7bd15ad0]>

【问题讨论】:

  • 为什么不用砖石?易于使用。如果你想更新约束,只需调用 mas_updateConstraints
  • Masonry 似乎是另一个帮助框架,可以更轻松地设置约束。我的问题似乎是视图层次结构中的调用(请参阅已编辑的问题)。

标签: ios uiview autolayout nslayoutconstraint


【解决方案1】:

您应该将这些视图限制为视图的宽度,而不是根据它计算的常数。

在 Objective-c 中看起来像

[NSLayoutConstraint constraintWithItem:container0
                             attribute:NSLayoutAtrributeWidth
                             relatedBy:NSLayoutRelationEqual
                                toItem:self
                             attribute:NSLayoutAttributeWidth
                            multiplier:(1.0f/7.0f)
                              constant:0];

这将为您提供一个始终为其父视图宽度的 1/7 的视图。

我猜在 C# 中会是这样

NSLayoutConstraint.Create (container0, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this, NSLayoutAttribute.Width, (1/7), 0);

【讨论】:

  • 非常感谢您的回复!对于我的测试项目,它确实有效,但我会在我的真实项目中尝试它。但是这个约束H:|-0-[container1][container2(==container1)][container3(==container1)][container4(==container1)][container5(==container1)][container6(==container1)][container0(==container1)]-0-| 有什么不同呢?结果应该是一样的,但事实并非如此。这样做时,我遇到了一个圆形问题(仅在 iOS 7 中)。您的 C# 尝试非常好!对于乘数,我必须选择 (1.0f / 7.0f) 才能使其起作用。
  • 是的,您没有理由不能将它们限制为都具有相同的宽度。你得到什么样的四舍五入问题?还有什么约束错误?
  • iPad 2 上的屏幕宽度为 1024 点。你不能把它除以七而没有余数。如果这样做,您会在视图之间或接近尽头时获得一些空间。所以你必须使用整数值来正确调整它的大小。为了实现这一点,一些元素必须比另一个元素更大/更小。这是我尝试过的,但自动布局和框架不能一起工作。我在我的问题中附加了自动布局错误。它发生在旋转之后。似乎以某种方式没有正确更新宽度和高度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多