25

我在我的应用程序中实现了一个自定义 UIViewController 转换,它取代了内置推送动画的导航控制器。

到目前为止一切正常,除了新推送的视图控制器中的 toplayoutguide 为 0 尽管新视图控制器继承了旧视图控制器的导航栏。它应该是 64.0(状态栏高度 + 导航栏高度),现在是 0.0。因此,连接到情节提要中顶部布局指南的所有对象现在显得过高 64 点(在半透明条下方)。

当我禁用自定义视图转换时,顶部布局指南将具有预期值。我试图“到处”调用 layoutSubviews 和 updateConstraints。在视图控制器以及导航控制器中。

据我了解,导航控制器(parentviewcontroller)应该更新新视图控制器的 toplayoutguide,但显然我在自定义转换代码中遗漏了一些东西,这会触发 toplayoutguide 更新为正确值。

这是我的自定义转换代码,它是一个设置为导航控制器委托的对象:

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
    return 0.7;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIView *animationContainerView = [transitionContext containerView];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = [toVC view];
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIView *fromView = [fromVC view];

    CGRect endFrame = [transitionContext finalFrameForViewController:toVC];
    CGRect startFrame;

    startFrame = CGRectOffset(endFrame, 0, endFrame.size.height);

    if (self.operation == UINavigationControllerOperationPop) {
        [animationContainerView insertSubview:toView belowSubview:fromView];
        [toView setFrame:endFrame];
    }
    else{
        [toView setFrame:startFrame];
        [animationContainerView insertSubview:toView aboveSubview:fromView];
    }

    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:0.8 options:UIViewAnimationOptionBeginFromCurrentState animations:^{

        if (self.operation == UINavigationControllerOperationPop) {
            [fromView setFrame:startFrame];
            [fromView layoutIfNeeded];
        }
        else{
            [toView setFrame:endFrame];
            [toView layoutIfNeeded];
        }

    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES];
    }];
}

那里没有什么特别的事情发生。只是从底部向上滑动的视图,带有一些内置的动态。

问题是,附加到顶部布局指南的对象现在位于导航栏下方,因为顶部布局指南长度 == 0。

我不知道我需要做什么,以便将视图控制器的 toplayoutguide 设置为正确的值。

推送导航是使用推送故事板 segue 执行的“普通香草”。在调用 performSegueWithIdentifier 之前,我所做的就是设置 navigationcontrollers 委托。

这是代码:

    self.navigationController.delegate = [[My_CustomNavigationTransitionDelegate alloc] init];
    [self performSegueWithIdentifier:@"infosSegue" sender:nil];

我想念什么?

4

4 回答 4

5

我遇到了一个问题,该bottomLayoutGuide属性会将自身设置为零长度,然后会导致标签栏上方的按钮下降到带有自动布局的标签栏下方。

你有没有看过这样做

[self.navigationController.view setNeedsLayout]

我把它放进我的viewwillappear,我不再得到零长度的bottomLayoutGuide财产。也许这也会帮助你处理你的topLayoutGuide财产。

于 2014-04-21T02:32:07.897 回答
0

我遇到了完全相同的问题。我的自定义导航控制器的容器视图没有约束。我将容器视图的垂直间距约束添加到其父视图的布局指南(尽管两者的大小相同),并在容器视图上设置顶部/底部/状态栏外观,一切正常,推送的布局指南控制器处于正确位置。希望有帮助。

更新:来自topLayoutGuide 的官方文档

容器视图控制器中的视图控制器不设置此属性的值。相反,容器视图控制器约束值以指示: 导航栏的底部,如果导航栏可见 状态栏的底部,如果只有状态栏可见 视图控制器视图的顶部边缘,如果两者都不可见状态栏和导航栏都不可见

所以容器视图需要实现正确的约束和隐藏/显示栏等才能使效果起作用。AFAIK 在自定义容器视图控制器中没有 API 可以执行此操作。

于 2014-06-15T18:21:56.913 回答
0

我找到了一个方法。在导航栏变为深色后,首先取消选中控制器的“扩展边缘”属性。将视图添加到控制器并设置顶部和底部 LayoutConstraint -100。然后将视图的clipsubview 属性设置为 no(用于 navigaionbar 半透明效果)。我的英语不好对不起。:)

于 2014-06-21T10:43:48.053 回答
0

我能够使用以下视图层次结构解决此问题:

UIView
 UIScrollView
  <content, constrained to UIScrollView>

约束UIScrollView以匹配UIView's顶部、前导、尾部和底部边缘。Interface Builder 可能希望您使用 topLayoutGuide 和 bottomLayoutGuide UIScrollView,或者它可能不会。也许它取决于 Xcode 的版本,但是我们的一些视图控制器使用了超级视图,其他的使用了布局指南。

对于 Interface Builder 不想相对于其父视图约束滚动视图的视图,我在文本编辑器中打开故事板并手动调整滚动视图上的约束。

最后,在 View Controller 上,确保 top bar 下的 extend edges 为 YES,Adjust Scroll View Insets 也是如此。

基本上,我避免使用 topLayoutGuide,而是依靠滚动视图插图,这确实有效。

在层次结构中没有 UIScrollView 的地方,就像你一样,不扩展顶部栏下的边缘对我有用。

于 2013-11-18T18:38:53.230 回答