【问题标题】:Auto layout, screen rotation and UIView animation自动布局、屏幕旋转和 UIView 动画
【发布时间】:2014-01-07 04:39:45
【问题描述】:

我遇到了一个 UIView 的问题,我将它添加到屏幕底部并在按下按钮时将其动画化以填充大部分屏幕。视图将上下动画并按预期旋转。如果我尝试在横向设置动画,它会中断并给我错误消息:

*** Assertion failure in -[UIScrollView _edgeExpressionInContainer:vertical:max:], /SourceCache/UIKit_Sim/UIKit-2380.17/NSLayoutConstraint_UIKitAdditions.m:2174
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Autolayout doesn't support crossing rotational bounds transforms with edge layout constraints, such as right, left, top, bottom. The offending view is: <UIView: 0x9199340; frame = (20 0; 748 1024); transform = [0, -1, 1, 0, 0, 0]; autoresize = RM+BM; layer = <CALayer: 0x91993d0>>'

有问题的视图是 self.view。

我如何创建 UIView:

[self.myContentView addSubview:subBar.filterListView];

[self.myContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[filterListView]|"
                                                                           options:0
                                                                           metrics:nil
                                                                             views:@{@"filterListView": subBar.filterListView}]];

subBar.filterListView.bottomConstraint = [NSLayoutConstraint constraintWithItem:subBar.filterListView
                                                                      attribute:NSLayoutAttributeBottom
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:self.mapView
                                                                      attribute:NSLayoutAttributeBottom
                                                                     multiplier:1
                                                                       constant:0];

subBar.filterListView.topConstraint = [NSLayoutConstraint constraintWithItem:subBar.filterListView
                                                                   attribute:NSLayoutAttributeTop
                                                                   relatedBy:NSLayoutRelationEqual
                                                                      toItem:self.mapView
                                                                   attribute:NSLayoutAttributeBottom
                                                                  multiplier:1
                                                                    constant:0];

[self.myContentView addConstraint:subBar.filterListView.bottomConstraint];
[self.myContentView addConstraint:subBar.filterListView.topConstraint];

self.myContentView 是一个占据了整个 self.view 的 UIView:

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:NSDictionaryOfVariableBindings(contentView)]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|"
                                                                         options:0
                                                                         metrics:nil
                                                                           views:NSDictionaryOfVariableBindings(contentView)]];    

要为 subBar.filterListView 设置动画,我删除了顶部和底部约束,重新分配它们,添加它们,然后设置动画:

[self.myContentView removeConstraint:view.topConstraint];
[self.myContentView removeConstraint:view.bottomConstraint];

view.topConstraint = [NSLayoutConstraint constraintWithItem:view
                                                  attribute:NSLayoutAttributeTop
                                                  relatedBy:NSLayoutRelationEqual
                                                     toItem:self.topToolBar
                                                  attribute:NSLayoutAttributeBottom
                                                 multiplier:1
                                                   constant:0];

view.bottomConstraint.constant -= SUB_BAR_SIZE.height;

[self.myContentView addConstraint:view.topConstraint];
[self.myContentView addConstraint:view.bottomConstraint];

[self.myContentView setNeedsUpdateConstraints];

[UIView animateWithDuration:.25 animations:^{
    [self.myContentView layoutIfNeeded];
}];

代码在旋转时会与顶部和底部混淆吗?它认为肖像的顶部是风景的左边吗?

【问题讨论】:

    标签: ios objective-c autolayout


    【解决方案1】:

    好的,我找到了解决方案。它并没有解决上述问题,而是找到了另一种解决方法。

    我将约束改为可视格式语言 (VFL) 方法:

    subBar.filterListView.verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[filtersSubBar][filterListView(0)]" options:0
                                                                                        metrics:nil
                                                                                          views:@{@"filterListView": subBar.filterListView, @"filtersSubBar" : subBar.filtersSubBar}];
    

    我认为问题在于使用了导致问题的属性NSLayoutAttributeTopNSLayoutAttributeRight 等。

    Autolayout 无法处理旋转并尝试使用 NSLayoutAttributeTop,而它本应更改为 NSLayoutAttributeRight 来表达新的方向。我想我们可以手动更改约束。

    似乎 VFL 处理它的方式不同并且不使用属性?

    这感觉好像它要么是一个错误,要么只是 iOS 的一个缺点。

    【讨论】:

      【解决方案2】:

      致来自谷歌的任何人:我在自定义 PushSegue 中调用 presentView 控制器时遇到了这个异常:

      @implementation PushSegue
      - (void) perform
      {
          UIViewController* fromController = (UIViewController*) self.sourceViewController;
          UIViewController* toController = (UIViewController*) self.destinationViewController;
      
          CATransition* transition = [CATransition animation];
      
          BOOL iPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
      
          transition.duration = iPad ? 0.5 : 0.3;
          transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
          transition.type = kCATransitionPush;
      
          switch ([UIApplication sharedApplication].statusBarOrientation)
          {
              case UIInterfaceOrientationPortraitUpsideDown:
                  transition.subtype = kCATransitionFromLeft;
                  break;
      
              case UIInterfaceOrientationLandscapeLeft:
                  transition.subtype = kCATransitionFromBottom;
                  break;
      
              case UIInterfaceOrientationLandscapeRight:
                  transition.subtype = kCATransitionFromTop;
                  break;
      
              default:
                  transition.subtype = kCATransitionFromRight;
                  break;
          }
      
          [fromController.view.window.layer addAnimation:transition forKey:nil];
      
          [fromController presentViewController:toController animated:NO completion:nil];
      }
      @end
      

      原因是我的代码中有一些误解:

      [self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
      

      (这是我的第一个 iOS 应用) 你不应该执行这样的调用,所以我删除了它,现在一切正常

      【讨论】:

        【解决方案3】:

        你说得对,自动布局不适用于影响 UI 对象对齐矩形的动画变换。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多