UIView transitionWithView 不起作用

Posted

技术标签:

【中文标题】UIView transitionWithView 不起作用【英文标题】:UIView transitionWithView doesn't work 【发布时间】:2011-09-30 22:21:14 【问题描述】:

这是测试项目中主视图控制器的 viewDidLoad:

- (void)viewDidLoad

[超级viewDidLoad];

UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 300, 300)];
[self.view addSubview:containerView];

UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
[redView setBackgroundColor:[UIColor redColor]];
[containerView addSubview:redView];

UIView *yellowView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
[yellowView setBackgroundColor:[UIColor yellowColor]];


[UIView transitionWithView:containerView duration:3
                   options:UIViewAnimationOptionTransitionFlipFromLeft animations:^
                       [redView removeFromSuperview];
                       [containerView addSubview:yellowView];
                   
                completion:NULL];

黄色框刚刚出现。无论我尝试哪个 UIViewAnimationOption 都没有动画。为什么???

编辑:我还尝试使用 performSelector withDelay 将动画移出 viewDidLoad 并进入另一个方法。结果相同 - 没有动画。

也试过这个: [UIView transitionFromView:redView toView:yellowView duration:3 options:UIViewAnimationOptionTransitionFlipFromLeft completion:NULL];

不过,黄色视图只是出现了。没有动画。

【问题讨论】:

【参考方案1】:

经过一些测试,您似乎无法在同一个运行循环中创建容器视图并设置动画并使其正常工作。为了使您的代码正常工作,我首先在viewDidLoad 方法中创建了containerViewredView。然后我把你的动画放到viewDidAppear 方法中。为了让我可以从viewDidAppear 方法中引用containerViewredView,我将它们设为属性。这是一个ST_ViewController.m 文件的代码,它将执行您想要的动画。

@interface ST_ViewController ()
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIView *redView;
@end

@implementation ST_ViewController

- (void)viewDidLoad

    [super viewDidLoad];
    [self setContainerView:[[UIView alloc] initWithFrame:CGRectMake(10, 10, 300, 300)]];
    [[self view] addSubview:[self containerView]];

    [self setRedView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)]];
    [[self redView] setBackgroundColor:[UIColor redColor]];
    [[self containerView] addSubview:[self redView]];


-(void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];



    UIView *yellowView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
    [yellowView setBackgroundColor:[UIColor yellowColor]];


    [UIView transitionWithView:[self containerView]
                      duration:3
                       options:UIViewAnimationOptionTransitionFlipFromLeft
                    animations:^(void)
                        [[self redView] removeFromSuperview];
                        [[self containerView] addSubview:yellowView];
                         

                    completion:nil];



@end

【讨论】:

我得出了同样的结论,但我想知道为什么会这样?有什么想法吗? 看看下面肯尼的回答。有些事情在 viewDidAppear 之前还没有完全设置。 不,这与它无关。如果您要添加视图然后在视图加载后执行动画,我说的是一般意义上的。不过,我已经想通了,更多信息在这里 - andrewmarinov.com/working-with-uiviews-transition-animations【参考方案2】:

不要把它放在viewDidLoad 中。 viewDidLoad 在视图完全加载到内存但尚未显示在屏幕上时调用。

尝试将上述代码放入viewDidAppear:,当视图出现在屏幕上时调用。

编辑:附带说明,如果 performSelector:withDelay: 修复了某些问题,则意味着您尝试做错了。你需要以某种方式重构。 performSelector:withDelay: 在 99.999% 的情况下解决问题的方法都是错误的。一旦您将此代码放在不同速度的设备(新 iPhone、旧 iPhone)上,它就会搞砸。

【讨论】:

将其移至 viewDidAppear 无效。不过,黄色视图只是出现,没有动画。 您的“旁注”陈述不正确。有些事情,尤其是 UIKit 中的很多事情,只需要在下次运行循环中发生,这样操作系统就有机会绘制它们。使用 -performSelector:withObject:afterDelay 是让操作系统有机会在动画之前更新视图、在上下文中渲染它等的好方法。0.0 的延迟足以在下一次运行循环传递时获得它。它不会根据设备搞乱时间。 @DaveBatton 这对我来说总是一种代码味道,但你是对的,这是一种观点,而不是事实。它本身可能没有错误,但总有一种更清洁的方式来做事(无论如何,99.999% 的时间)。

以上是关于UIView transitionWithView 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 Xamarin 中使用 transitionWithView 设置 UIView.Hidden 属性时淡化动画

UIImage Cross Dissolve 不使用 UIView transitionWithView 制作动画

带有 UILabel 的 UIView transitionWithView 在过渡期间会丢失圆角

使用动画块之外的更改时,UIView transitionWithView 是平滑的

UIView transitionWithView 带有多个xib文件的子视图

transitionWithView 和 animateWithDuration 的问题