【问题标题】:The constraints doesn't work as I expected约束没有按我预期的那样工作
【发布时间】:2014-11-17 05:12:04
【问题描述】:

我有两个这样的观点:

我设置了垂直空间限制:

如您所见,BottomView 的顶部和 TopView 的底部之间的约束为 0。但不幸的是,当我单击 Toggle 按钮移动顶部视图时,它不是真的。代码如下:

@IBAction func onToggle(sender: AnyObject) {

    self.topView.transform = CGAffineTransformMakeTranslation(0, -self.topView.bounds.height)
}

即使我添加它也是一样的:

    self.view.setNeedsUpdateConstraints()
    self.view.setNeedsLayout()

结果是:

显然 TopView 的底部和 BottomView 的顶部之间的边距不是 0。自动布局不起作用。我错过了什么吗?谢谢

P.S.:我知道还有另一种方法可以解决这个问题。例如,在按下切换按钮时更改 BottomView 的框架。但我的问题是为什么自动布局不能按我的预期工作?

【问题讨论】:

    标签: ios swift autolayout nslayoutconstraint


    【解决方案1】:

    我认为这可能与 TopView 的约束有关。当您将平移变换应用到顶视图时,TopView 的框架发生了变化。所以它的上边距约束也发生了变化。这会影响底视图的上边距约束。

    我的建议是不要对 UIView 应用翻译转换。而是更改顶视图的顶部垂直空间约束。

        self.topConstraint.constant = -self.topView.bounds.height
    

    底部视图将以这种方式跟随顶部视图。这意味着自动布局确实有效。希望它会有所帮助。

    【讨论】:

      【解决方案2】:

      似乎 iOS 8 有一个调整 UILabel 高度约束的错误。

      无论如何,假设您的两个视图不是 UILabel,我建议使用的方法是创建一个属性来记住您的顶视图的高度约束:

      @interface ViewController : UIViewController
      
      @property (nonatomic, strong) UIView *topView;
      @property (nonatomic, strong) UIView *bottomView;
      
      // -----------------------------------------------------------
      // We will animate this NSLayoutConstraint's constant value
      // -----------------------------------------------------------
      @property (nonatomic, strong) NSLayoutConstraint *topViewHeightConstraint;
      
      @end
      

      然后设置我们的视图和切换按钮:

      - (void)viewDidLoad {
          [super viewDidLoad];
          // Do any additional setup after loading the view, typically from a nib.
      
          [self initViews];
          [self initConstraints];
      }
      
      - (void)didReceiveMemoryWarning {
          [super didReceiveMemoryWarning];
          // Dispose of any resources that can be recreated.
      }
      
      -(void)initViews
      {
          self.edgesForExtendedLayout = UIRectEdgeNone;
          self.navigationController.navigationBar.translucent = NO;
      
          self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Toggle" style:UIBarButtonItemStylePlain target:self action:@selector(toggleTopView)];
      
          self.topView = [[UIView alloc] init];
          self.topView.backgroundColor = [UIColor colorWithRed:203.0/255.0 green:89.0/255.0 blue:91.0/255.0 alpha:1.0];
      
          self.bottomView = [[UIView alloc] init];
          self.bottomView.backgroundColor = [UIColor colorWithRed:103.0/255.0 green:167.0/255.0 blue:187.0/255.0 alpha:1.0];
      
          [self.view addSubview:self.topView];
          [self.view addSubview:self.bottomView];
      }
      
      -(void)initConstraints
      {
          self.topView.translatesAutoresizingMaskIntoConstraints = NO;
          self.bottomView.translatesAutoresizingMaskIntoConstraints = NO;
      
          self.topView.layoutMargins = UIEdgeInsetsZero;
          self.bottomView.layoutMargins = UIEdgeInsetsZero;
      
          id views = @{
                       @"topView": self.topView,
                       @"bottomView": self.bottomView
                       };
      
          [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[topView]|" options:0 metrics:nil views:views]];
      
          [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[bottomView]|" options:0 metrics:nil views:views]];
      
      
          [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topView][bottomView]|" options:0 metrics:nil views:views]];
      
          self.topViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self.topView
                                                                      attribute:NSLayoutAttributeHeight
                                                                      relatedBy:NSLayoutRelationEqual toItem:nil
                                                                      attribute:NSLayoutAttributeHeight
                                                                     multiplier:1.0 constant:170.0];
      
          [self.view addConstraint:self.topViewHeightConstraint];
      }
      
      -(void)toggleTopView
      {
          if(self.topViewHeightConstraint.constant != 0)
          {
              self.topViewHeightConstraint.constant = 0;
          }
          else
          {
              self.topViewHeightConstraint.constant = 170.0;
          }
      
          [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{
      
              [self.view layoutIfNeeded];
      
          } completion:nil];
      
      
      }
      

      你一开始就明白了:

      然后当你点击切换按钮时,我们将 heightConstraint 属性常量设置为 0:

      -(void)toggleTopView
      {
          if(self.topViewHeightConstraint.constant != 0)
          {
              self.topViewHeightConstraint.constant = 0;
          }
          else
          {
              self.topViewHeightConstraint.constant = 170.0;
          }
      
          [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{
      
              [self.view layoutIfNeeded];
      
          } completion:nil];
      }
      

      你会得到一个平滑的红色折叠动画:

      【讨论】:

      • 谢谢。我使用相同的方法来创建动画。
      【解决方案3】:

      在布局代码的其余部分完成后应用视图上的变换。这包括自动布局,因此如果您更改视图的转换,它不会影响自动布局。变换将相对于自动布局放置视图的位置。

      【讨论】:

        猜你喜欢
        • 2022-08-02
        • 1970-01-01
        • 1970-01-01
        • 2021-01-16
        • 1970-01-01
        • 1970-01-01
        • 2016-06-19
        • 2013-04-11
        • 1970-01-01
        相关资源
        最近更新 更多