iOS7自定义ViewController转换和顶部布局指南

时间:2013-11-05 12:37:56

标签: ios iphone objective-c ios7

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

到目前为止一切都有效,除了新推出的视图控制器中的toplayoutguide为0,尽管新视图控制器从旧视图控制器继承了导航栏。 它应该是64.0(状态栏高度+导航栏高度),现在它是0.0。 因此,附加到故​​事板中顶部布局指南的所有对象现在显示为64点太高(在半透明条下方)。

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

据我所知,navigationcontroller(parentviewcontroller)应更新新视图控制器的toplayoutguide,但显然我在自定义转换代码中缺少某些内容,这会触发更新为toplayoutguide的正确值。

这是我的自定义转换代码,它是一个设置为navigationcontroller委托的对象:

- (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 个答案:

答案 0 :(得分:5)

我遇到一个问题,bottomLayoutGuide属性会将自身设置为零长度,然后会导致标签栏上方的按钮低于标签栏以及自动布局。

你看过这个吗

[self.navigationController.view setNeedsLayout]

我把它放到我的viewwillappear中,我在bottomLayoutGuide属性上停止了零长度。也许这会帮助你了解topLayoutGuide财产。

答案 1 :(得分:0)

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

UIView
 UIScrollView
  <content, constrained to UIScrollView>

限制UIScrollView以匹配UIView's顶部,前导,尾随和底部边缘。 Interface Builder可能希望您使用top UIScrollView的topLayoutGuide和bottomLayoutGuide,否则可能不会。也许它取决于Xcode的版本,但我们的一些View控件使用了superview,其他人使用了布局指南。

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

最后,在视图控制器上,确保顶部栏下方的延伸边缘为“是”,调整滚动视图插图也是如此。

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

我在层次结构中没有UIScrollView,就像你一样,不在顶部栏下方扩展边缘为我工作。

答案 2 :(得分:0)

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

更新:来自official documentation on topLayoutGuide

  

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

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

答案 3 :(得分:0)

我发现了一种方法。首先取消选中控制器的&#34; Extend Edges&#34; 属性,导航栏将变为深色。添加视图到控制器和设置顶部和底部LayoutConstraint -100 。然后查看 clipsubview属性否(对于navigaionbar transculent effect)。我的英语很抱歉。 :)