【问题标题】:Constraints not getting updated when changing bounds origin of UIView更改 UIView 的边界原点时约束未更新
【发布时间】:2019-10-31 19:40:43
【问题描述】:

我有一个 UIView A,其中包含另一个 UIView B(A 的子视图)。还有另一个 UIView C(UIView A 的父视图的子视图),它应用了约束,使得 UIView C 的顶部锚点与 UIView B 的底部锚点对齐,UIView C 的左锚点与 UIView 的左锚点对齐B.

现在,当我尝试更改 UIView A 的边界原点时,UIView B 的位置会更新,但 UIView C 的位置没有改变,导致破坏了原来的约束。

我尝试执行 setNeedsLayout 和 updateConstraints,但没有任何效果。

当 UIView C 是 UIView A 的子级时,它可以正常工作。

如何保持 UIView C 是 UIView A 的兄弟,并在改变 UIView A 的边界原点的同时保持约束?

【问题讨论】:

  • 没有代码很难说哪里出了问题
  • 我在这里分享了代码 - ideone.com/WhF3Uf

标签: ios uiview autolayout


【解决方案1】:

首先,你有一个小错误

UIView C 的左锚点与 UIView B 的左锚点对齐。

NSLayoutConstraint *left = [myView.leftAnchor constraintEqualToAnchor:secondView.rightAnchor constant:0];

尝试调用

[self.view layoutIfNeeded];

边界改变后

【讨论】:

  • 感谢您的建议。我已经尝试过 layoutIfNeeded/setNeedsLayout/updateConstraints 但似乎都没有。
  • 当您更改 UIView A 的边界时,您希望 UIView C 保持在该位置上还是希望它也移动?
  • 我也想移动它。
【解决方案2】:

您正在尝试将显式框架/边界设置与自动布局约束混合并匹配。如您所见,这行不通。

当你运行这一行时:

[[recognizer view] setBounds:CGRectMake(100, 100, bounds.size.width, bounds.size.height)];

您正在更改视图的 bounds。这不会改变任何约束。 (实际上,设置bounds 甚至不会更改frame,但这是另一个问题。)

如果您想移动一个视图,并保持该视图与其他元素之间的约束,您需要更新该视图上的 约束,而不是其边界(或框架)。

因此,您希望保留对约束的引用,或在需要时找到它们,并根据需要更新 .constant 值。

以下是通过查找 CenterX 和 CenterY 约束(而不是保存引用)来更改点击视图中心的示例:

- (void)handleGesture:(UIGestureRecognizer*)recognizer
{

    // get the view that was tapped
    UIView *tappedView = [recognizer view];

    // get that view's constraints
    NSArray *constraints = [tappedView constraints];

    // we want to find the CenterX constraint
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute = %d", NSLayoutAttributeCenterX];
    NSArray *filteredArray = [constraints filteredArrayUsingPredicate:predicate];

    // if it doesn't have a CenterX constraint, return
    if(filteredArray.count == 0){
        return;
    }
    NSLayoutConstraint *centerX =  [filteredArray objectAtIndex:0];

    // we want to find the CenterY constraint
    predicate = [NSPredicate predicateWithFormat:@"firstAttribute = %d", NSLayoutAttributeCenterY];
    filteredArray = [constraints filteredArrayUsingPredicate:predicate];

    // if it doesn't have a CenterY constraint, return
    if(filteredArray.count == 0){
        return;
    }
    NSLayoutConstraint *centerY =  [filteredArray objectAtIndex:0];

    // we now have references to the CenterX and CenterY constraints of the tapped view,
    // so we can change the .constant values and the related constraints to the other view will be maintained

    [UIView animateWithDuration:0.15
                     animations:^
     {
         centerX.constant -= 100.0;
         centerY.constant -= 100.0;
     }
                     completion:^(BOOL finished)
     {

     }];

}

【讨论】:

  • 感谢您的澄清和很好的解释。就我而言,我只想更改视图的边界。原因是我想显示一个当前剪辑在底部的子视图。但是,虽然我想更改边界,但我还想保持在任何其他视图上设置的原始约束,以及我正在更改边界的视图内的任何子视图。
  • 你想改变bounds还是frame
  • 我想改变边界。
  • @Vishwas - 您可能需要重新考虑您的方法,因为自动布局/约束与边界无关。
猜你喜欢
  • 2018-06-15
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 2023-03-04
相关资源
最近更新 更多