【问题标题】:Subviews Not Positioned Correctly During Animation动画期间未正确定位子视图
【发布时间】:2012-12-15 05:38:46
【问题描述】:

我有一个简单的动画,我正在从旧视图的中心扩展一个新视图,而那个视图会淡出。然而,这个新视图的子视图(一个按钮和一个标签)从屏幕的右下角“飞”进来,因为这个新视图扩展到占据整个屏幕。我尝试过打开和不打开自动布局,虽然这两种情况给出了不同的结果,但它们都是错误的。

设置很简单,我在故事板中有两个未连接的视图控制器,并使用以下代码为视图更改设置动画:

-(void)switchViews2:(id)sender {
    UIWindow *win = self.view.window;
    YellowController *yellow = [self.storyboard instantiateViewControllerWithIdentifier:@"Yellow"];
    yellow.view.frame = CGRectMake(0, 0, 1, 1);
    yellow.view.center = self.view.center;
    [win addSubview:yellow.view];
    CGRect  frame = self.view.frame;
    [UIView animateWithDuration:5 animations:^{
        yellow.view.frame = frame;
        self.view.alpha = 0;
    }
             completion:^(BOOL finished) {
                 [self.view removeFromSuperview];
                 win.rootViewController = yellow;
         }];
}

问题是,为什么子视图在动画时不停留在它们应该在其父视图内的位置。

【问题讨论】:

    标签: ios uiviewanimation


    【解决方案1】:

    要使子视图就位,尤其是在使用 Autolayout 时,动画转换属性而不是框架要简单得多。这样子视图的 bounds 属性不会改变,所以在动画过程中它不会觉得需要一直中继它的子视图。

    添加您的子视图及其最终帧,将其变换设置为例如 0.1 的缩放仿射变换,然后将其动画化为恒等变换。它将从中心点长出来,所有子视图都在正确的位置。

    【讨论】:

    • 谢谢,我对变换没有太多经验,所以我倾向于忘记这种做事方式。我想我应该读一读。
    【解决方案2】:

    问题在于布局约束。如果不是在动画块中设置视图框架,而是在窗口和新视图之间添加约束,然后在动画块中调用 layoutIfNeeded 它可以正常工作:

    -(void)switchViews2:(id)sender {
        UIWindow *win = self.view.window;
        YellowController *yellow = [self.storyboard instantiateViewControllerWithIdentifier:@"Yellow"];
        [yellow.view setTranslatesAutoresizingMaskIntoConstraints:NO];
        yellow.view.frame = CGRectMake(0, 0, 1, 1);
        yellow.view.center = self.view.center;
        [win addSubview:yellow.view];
    
        NSLayoutConstraint *con1 = [NSLayoutConstraint constraintWithItem:yellow.view attribute:NSLayoutAttributeLeading relatedBy:0 toItem:win attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
        NSLayoutConstraint *con2 = [NSLayoutConstraint constraintWithItem:yellow.view attribute:NSLayoutAttributeTop relatedBy:0 toItem:win attribute:NSLayoutAttributeTop multiplier:1 constant:20];
        NSLayoutConstraint *con3 = [NSLayoutConstraint constraintWithItem:yellow.view attribute:NSLayoutAttributeTrailing relatedBy:0 toItem:win attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
        NSLayoutConstraint *con4 = [NSLayoutConstraint constraintWithItem:yellow.view attribute:NSLayoutAttributeBottom relatedBy:0 toItem:win attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
    
        [win addConstraints:@[con1,con2,con3,con4]];
    
        [UIView animateWithDuration:1 animations:^{
            [win layoutIfNeeded];
            self.view.alpha = 0;
        }
                 completion:^(BOOL finished) {
                     [self.view removeFromSuperview];
                     win.rootViewController = yellow;
             }];
    }
    

    【讨论】:

    • 请注意,如果您碰巧使用了完整的表单animateWithDuration:delay:options:animations:completion:,您可以传递UIViewAnimationOptionLayoutSubviews,它会为您执行layoutIfNeeded
    • @robmayoff,实际上这在这种情况下不起作用。如果我包含该选项,我不会得到动画——它会跳转到最终条件。
    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多