【问题标题】:iPhone - Autolayout issue on rotate with three stacked viewsiPhone - 使用三个堆叠视图旋转时的自动布局问题
【发布时间】:2014-05-23 09:57:04
【问题描述】:

我有三个类似这样的视图:

我希望它们在设备旋转时移动到这样的位置:

注意:实际视图也将在此方向上彼此相邻,图片仅用于演示。

我在 AutoLayout 上玩了一整天,但无法让它工作。我应该加载一个正确定位子视图的全新视图,还是确实有办法使用神奇的 AutoLayout 来做到这一点?

【问题讨论】:

  • 子类化视图,覆盖 updateConstraints 并在代码中设置约束。在控制器中添加方向更改通知并调用 setNeedsLayout
  • 我需要在哪个视图上更新约束?主视图还是三个子视图?谢谢!
  • 好的,我覆盖了 updateConstraints,但它的工作方式似乎与使用情节提要没有任何不同。我很可能没有完全正确地做到这一点,因为这是我第一次在代码中编写约束。你有例子吗?

标签: iphone objective-c storyboard interface-builder autolayout


【解决方案1】:

可以通过代码轻松实现所需的 UI。

首先在 viewDidLoad 方法中以编程方式添加三个视图。在 viewDidLoad 中,我们将根据方向应用约束。

    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    _constraints = [NSMutableArray array];

    _view1 = [[UIView alloc] init];
    _view1.translatesAutoresizingMaskIntoConstraints = NO;
    _view1.backgroundColor = [UIColor greenColor];
    [self.view addSubview:_view1];

    _view2 = [[UIView alloc] init];
    _view2.translatesAutoresizingMaskIntoConstraints = NO;
    _view2.backgroundColor = [UIColor redColor];
    [self.view addSubview:_view2];

    _view3 = [[UIView alloc] init];
    _view3.translatesAutoresizingMaskIntoConstraints = NO;
    _view3.backgroundColor = [UIColor blueColor];
    [self.view addSubview:_view3];


    switch ([self.view viewOrientation]) {
        case ViewOrientationPortrait:
            [self setConstraintsForPortrait];
            break;
        case ViewOrientationLandscape:
            [self setConstraintsForLandScape];
            break;
        default:
            break;
    }
}

此方法为横向模式添加约束。它首先删除了我们可能在纵向模式中添加的所有先前添加的约束。

- (void)setConstraintsForLandScape {
    for (id c in _constraints) {
        [self.view removeConstraints:c];
    }
    [_constraints removeAllObjects];

    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_view1][_view2(==_view1)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view1, _view2)]];
    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_view3]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view3)]];
    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_view1][_view3(==_view1)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view1, _view3)]];

    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_view2(==_view1)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view1, _view2)]];

    for (id c in _constraints) {
        [self.view addConstraints:c];
    }
}

这里我们再次为纵向模式添加约束,首先删除任何先前添加的约束。

- (void)setConstraintsForPortrait {
    for (id c in _constraints) {
        [self.view removeConstraints:c];
    }
    [_constraints removeAllObjects];

    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_view1]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view1)]];
    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_view2]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view2)]];
    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_view3]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view3)]];

    [_constraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_view1][_view2(==_view1)][_view3(==_view1)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_view1, _view2, _view3)]];

    for (id c in _constraints) {
        [self.view addConstraints:c];
    }
}

此方法将处理方向转换

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    // Code here will execute before the rotation begins.
    // Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]
    NSLog(@"%@", NSStringFromCGSize(size));

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {

        // Place code here to perform animations during the rotation.
        // You can pass nil or leave this block empty if not necessary.
        switch ([self.view viewOrientation]) {
            case ViewOrientationPortrait:
                [self setConstraintsForPortrait];
                break;
            case ViewOrientationLandscape:
                [self setConstraintsForLandScape];
                break;
            default:
                break;
        }

    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {

        // Code here will execute after the rotation has finished.
        // Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]

    }];
}

【讨论】:

    【解决方案2】:

    感谢上面的评论,以及this 帖子中的选定答案,我得到了它的工作。以下是一些需要计算的其他步骤。

    在情节提要中设置约束,然后在视图的类中创建一个 NSLayoutConstraint IBOutlet @property (strong, nonatomic) IBOutlet NSLayoutConstraint *heightToTop; 并将它们链接到 IB 中设置的约束。然后,在您的视图控制器中,您调用 willRotateToInterfaceOrientation:duration,它将根据方向更新约束。

    -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
        {
            _redView.heightToTop.constant = 20.0f;
            _redView.distToLeft.constant = 20.0f;
            _greenView.distToRight.constant = 20.0f;
            _greenView.heightToTop.constant = 20.0f;
            _yelView.heightFromBottom.constant = 20.0f;
            [_yelView setNeedsUpdateConstraints];
            [_greenView setNeedsUpdateConstraints];
            [_redView setNeedsUpdateConstraints];
        }
    }
     else if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
        {
    
            _redView.heightToTop.constant = 58.0f;
            _redView.distToLeft.constant = 61.0f;
            _greenView.distToRight.constant = 39.0f;
            _greenView.heightToTop.constant = 222.0f;
            _yelView.heightFromBottom.constant = 63.0f;
            [_yelView setNeedsUpdateConstraints];
            [_greenView setNeedsUpdateConstraints];
            [_redView setNeedsUpdateConstraints];
        }
    

    当肖像再次出现时,我必须将它们放回去,但这并不太难,只要记住它们都在哪里。可能有更简单的方法可以将它们放回去,但我还没有找到。

    【讨论】:

      猜你喜欢
      • 2012-10-02
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 2015-08-11
      相关资源
      最近更新 更多