【问题标题】:UIView animated changes with auto layout constraints具有自动布局约束的 UIView 动画更改
【发布时间】:2014-01-27 15:24:12
【问题描述】:

假设我有一个如下所示的项目:

有两个UIViews - 一个叫yellowBox,另一个叫redBox。自动布局约束规定yellowBox 距离父视图顶部 60 点,前后有 350 点空格(即视图的左侧和右侧)。 redBox 具有相同的前导和尾随空格约束。两个 0 框之间存在垂直空间约束,表示yellowBox 的底部应始终直接位于redBox 的顶部。

当用户点击展开黄色框按钮时,我希望yellowBox 的高度增加,因此redBox 向下移动以继续满足垂直空间限制(即yellowBox始终位于redBox) 之上。这是动画代码:

- (IBAction)expandYellowBox:(id)sender {

    [UIView animateWithDuration:0.5
                     animations:^{
                         CGRect newFrame = self.yellowBox.frame;
                         newFrame.size.height += 50;
                         self.yellowBox.frame = newFrame;
                     }];

}

但是,我无法让它正常工作。从红色图标可以看出,此时的约束有问题:

这很公平,因为自动布局无法知道框的高度。但是,我不知道如何以允许调整框大小和移动框的方式解决此问题。例如,如果我在 yellowBox 上指定高度约束,那么这将阻止它被调整大小。如果我将高度约束设置为大于或等于(以允许yellowBox 高度增加),那么我会得到一个不同的约束错误:

所有约束均已在情节提要中使用 Xcode 建立 - 没有一个是用代码编写的。

非常感谢任何帮助。


编辑: 事实证明,单击按钮时yellowBox 正在增长——只是我无法分辨,因为它出现在redBox 后面。我只是在点击它大约四次后才注意到它开始出现在redBox 的底部。然而,同样的问题仍然存在——如何让redBox 始终粘在yellowBox 的底部。

【问题讨论】:

  • 你能检查一下你的 viewController 中是否调用了 viewDidLayoutSubViews 方法吗?执行点击事件时。
  • 不,viewDidLayoutSubViews 方法没有被调用。
  • 尝试设置边界而不是框架可能会工作一段时间。甚至重复 self.yellowBox.frame = newFrame;在你的代码中两次也可能修复一些时间
  • 这似乎不起作用,加上多次重复代码(直到需要)似乎不是解决问题的最佳方法......
  • 检查我的答案和演示。这会有所帮助

标签: ios cocoa-touch uiview autolayout


【解决方案1】:

按照shwet-solanki的方法试试,但是在修改约束后添加下面一行:

[self.view layoutIfNeeded];

IBAction 看起来像:

- (IBAction)expandYellowBox:(id)sender {

[UIView animateWithDuration:0.5
                 animations:^{
                     self.yellowBoxHeightConstraint.constant += 50;
                     [self.view layoutIfNeeded];
                 }];
}

其中yellowBoxHeightConstraintIBOutlet 的高度约束yellowBox。 希望这可以帮助。

【讨论】:

  • 感谢您的建议,但这是我试图避免的确切方法。我不想手动调整redBox 的框架,因为它应该由于约束而移动。在这种情况下这很简单,但这个问题中的示例只是一个演示问题的测试项目 - 实际问题发生在一个更大的项目中,不幸的是,使用您建议的方法是不可行或不可维护的。
  • 我希望你注意到我已经编辑了我的答案。当前的方法应该有效。试试看吧。
  • 我也发了一个后续问题:stackoverflow.com/questions/21033146/…
  • 你让我参加了面试......谢谢.. !!
  • 小心 layoutIfNeeded,因为它会立即执行布局,并且在某些情况下可能会导致不良影响(例如,当您从 scrollView:didScroll 使用它来将动画与视图的滚动联系起来时,触发很多事件)。这也是非常苛刻的。在这些情况下,最好使用 setNeedsLayout,它会在 UI 线程有时间时进行布局。
【解决方案2】:
//
//  WPViewController.h
//  AutoLayoutTEst
//
//  Created by VASANTH K on 09/01/14.
//  
//

#import <UIKit/UIKit.h>

@interface WPViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIButton *button1;
- (IBAction)buttClicked:(id)sender;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *heightConstrain;

@property (strong, nonatomic) IBOutlet UIButton *button2;
@end

点击事件

- (IBAction)buttClicked:(id)sender {


    self.heightConstrain.constant=100;


}

在这里,您需要为黄色按钮设置heightConstrain,然后为该按钮创建参考插座,然后更新heightConstrain 以更新该按钮的大小,它会自动将您的红色按钮向下移动。

https://github.com/vasanth3008/AutoLayoutHeighDemo

参考我的示例演示项目

【讨论】:

    【解决方案3】:
    1. 为两个视图添加高度约束
    2. 为黄色框的高度约束创建一个 IBOutlet
    3. 现在不是在按钮按下事件中更改黄色框的高度,而是更改高度约束的值。即假设您的 IBOutlet 约束名称是 yellowBoxHeightConstraint,然后是 yellowBoxHeightConstraint.constant += 50;

    希望这对你有用。

    【讨论】:

    • 谢谢,这确实扩展了yellowBox(将redBox 固定在yellowBox 的底部),但它不会为更改设置动画 - 它是突然发生的。
    猜你喜欢
    • 2014-05-26
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 2018-05-02
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多