gpt4 book ai didi

ios - 自定义容器 Controller : transitionFromViewController: View not properly layed-out before animation

转载 作者:IT王子 更新时间:2023-10-29 07:57:59 25 4
gpt4 key购买 nike

这既是一个问题也是一个 部分 解决方案。

*示例项目在这里:

https://github.com/JosephLin/TransitionTest

问题一:

使用时 transitionFromViewController:... , 布局由 toViewController 完成的 viewWillAppear:过渡动画开始时不显示。换句话说,预布局 View 在动画期间显示,并且它的内容在动画之后捕捉到布局后位置。

问题2:

如果我自定义导航栏的背景 UIBarButtonItem ,条形按钮在动画之前显示错误的大小/位置,并在动画结束时捕捉到正确的大小/位置,类似于问题 1。

为了演示这个问题,我制作了一个基本的自定义容器 Controller ,它执行一些自定义 View 转换。它几乎是一个 UINavigationController 副本,它会交叉溶解而不是在 View 之间推送动画。

“推送”方法如下所示:

- (void)pushController:(UIViewController *)toViewController
{
UIViewController *fromViewController = [self.childViewControllers lastObject];

[self addChildViewController:toViewController];
toViewController.view.frame = self.view.bounds;

NSLog(@"Before transitionFromViewController:");
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{}
completion:^(BOOL finished) {
[toViewController didMoveToParentViewController:self];
}];
}

现在, DetailViewController (我正在推送的 View Controller )需要在 viewWillAppear: 中布局其内容.在 viewDidLoad里做不到因为当时它没有正确的框架。

出于演示目的, DetailViewControllerviewDidLoad 中将其标签设置为不同的位置和颜色, viewWillAppear , 和 viewDidAppear :
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%s", __PRETTY_FUNCTION__);
CGRect rect = self.descriptionLabel.frame;
rect.origin.y = 50;
self.descriptionLabel.frame = rect;
self.descriptionLabel.text = @"viewDidLoad";
self.descriptionLabel.backgroundColor = [UIColor redColor];
}

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"%s", __PRETTY_FUNCTION__);
CGRect rect = self.descriptionLabel.frame;
rect.origin.y = 200;
self.descriptionLabel.frame = rect;
self.descriptionLabel.text = @"viewWillAppear";
self.descriptionLabel.backgroundColor = [UIColor yellowColor];
}

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"%s", __PRETTY_FUNCTION__);
CGRect rect = self.descriptionLabel.frame;
rect.origin.y = 350;
self.descriptionLabel.frame = rect;
self.descriptionLabel.text = @"viewDidAppear";
self.descriptionLabel.backgroundColor = [UIColor greenColor];
}

现在,当推送 DetailViewController 时,我期待在 y =200 看到标签在动画开头(左图),然后跳转到 y = 350动画完成后(右图)。

enter image description here enter image description here
动画前后的预期 View 。

但是,标签位于 y=50 ,好像是在 viewWillAppear 中制作的布局在动画发生之前没有成功(左图)。但请注意,标签的背景设置为黄色(由 viewWillAppear 指定的颜色)!

enter image description here enter image description here
动画开头的布局错误。请注意,条形按钮也以错误的位置/大小开始。

控制台日志
TransitionTest[49795:c07] -[DetailViewController viewDidLoad]
TransitionTest[49795:c07] 在 transitionFromViewController 之前:
TransitionTest[49795:c07] -[DetailViewController viewWillAppear:]
TransitionTest[49795:c07] -[DetailViewController viewWillLayoutSubviews]
TransitionTest[49795:c07] -[DetailViewController viewDidLayoutSubviews]
TransitionTest[49795:c07] -[DetailViewController viewDidAppear:]
请注意 viewWillAppear:被称为 AFTER transitionFromViewController:

问题1的解决方案

好了,部分解决方案到了。通过显式调用 beginAppearanceTransition:endAppearanceTransitiontoViewController , View 将在过渡动画发生之前具有正确的布局:
- (void)pushController:(UIViewController *)toViewController
{
UIViewController *fromViewController = [self.childViewControllers lastObject];

[self addChildViewController:toViewController];
toViewController.view.frame = self.view.bounds;

[toViewController beginAppearanceTransition:YES animated:NO];

NSLog(@"Before transitionFromViewController:");
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{}
completion:^(BOOL finished) {
[toViewController didMoveToParentViewController:self];
[toViewController endAppearanceTransition];
}];
}

请注意 viewWillAppear:现在被称为 BEFORE transitionFromViewController:
TransitionTest[18398:c07] -[DetailViewController viewDidLoad]
TransitionTest[18398:c07] -[DetailViewController viewWillAppear:]
TransitionTest[18398:c07] 在 transitionFromViewController 之前:
TransitionTest[18398:c07] -[DetailViewController viewWillLayoutSubviews]
TransitionTest[18398:c07] -[DetailViewController viewDidLayoutSubviews]
TransitionTest[18398:c07] -[DetailViewController viewDidAppear:]

但这并不能解决问题 2!

无论出于何种原因,导航栏按钮在过渡动画开始时仍以错误的位置/大小开始。我花了很多时间试图找到正确的解决方案,但没有运气。我开始觉得这是 transitionFromViewController: 中的一个错误或 UIAppearance管他呢。请您对此问题提供任何见解,我们将不胜感激。谢谢!

我尝试过的其他解决方案
  • 调用 [self.view addSubview:toViewController.view];之前 transitionFromViewController:

  • 它实际上为用户提供了完全正确的结果,解决了问题 1 和 2。问题是, viewWillAppearviewDidAppear两者都会被调用两次!如果我想在 viewDidAppear 中做一些扩展的动画或计算是有问题的.
  • 调用 [toViewController viewWillAppear:YES];之前 transitionFromViewController:

  • 我认为这与拨打 beginAppearanceTransition: 几乎相同.它解决了问题 1 但不解决问题 2。另外,文档说不要打电话 viewWillAppear直接地!
  • 使用 [UIView animateWithDuration:]而不是 transitionFromViewController:

  • 像这样:
    [self addChildViewController:toViewController];
    [self.view addSubview:toViewController.view];
    toViewController.view.alpha = 0.0;
    [UIView animateWithDuration:0.5 animations:^{
    toViewController.view.alpha = 1.0;
    } completion:^(BOOL finished) {
    [toViewController didMoveToParentViewController:self];
    }];

    它修复了问题 2,但 View 以 viewDidAppear 中的布局开始(标签为绿色,y=350)。此外,交叉溶解不如使用 UIViewAnimationOptionTransitionCrossDissolve

    最佳答案

    好的,将 layoutIfNeeded 添加到 toViewController.view 似乎可以解决问题 - 这可以在 View 显示在屏幕上之前正确布局(没有添加/删除),并且不再有奇怪的双重 viewDidAppear: 调用。

    - (void)pushController:(UIViewController *)toViewController
    {
    UIViewController *fromViewController = [self.childViewControllers lastObject];

    [self addChildViewController:toViewController];

    toViewController.view.frame = self.view.bounds;
    [toViewController.view layoutIfNeeded];

    NSLog(@"Before transitionFromViewController:");
    [self transitionFromViewController:fromViewController
    toViewController:toViewController
    duration:0.5
    options:UIViewAnimationOptionTransitionCrossDissolve
    animations:^{}
    completion:^(BOOL finished) {
    }];

    }

    关于ios - 自定义容器 Controller : transitionFromViewController: View not properly layed-out before animation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14632064/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com