iPhone - 使用三个堆叠视图旋转时的Autolayout问题

时间:2014-04-09 22:49:06

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

我有三种观点: StackedViews

我想让它们在旋转设备时移动到这样的东西: enter image description here

注意:真实视图也会在此方向上彼此相邻,图片仅供演示。

我一直在使用AutoLayout玩这个,但无法让它工作。我应该在正确定位子视图的情况下加载一个全新的视图,还是确实有办法用神奇的AutoLayout执行此操作?

2 个答案:

答案 0 :(得分: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:]

    }];
}

答案 1 :(得分:0)

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

在storyboard中设置约束,然后在视图的类中创建一个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];
    }

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