我在我的应用程序中实现了一个自定义的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];
我想念什么?
答案 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)