导航控制器顶部布局指南不支持自定义转换 [英] Navigation controller top layout guide not honored with custom transition

查看:22
本文介绍了导航控制器顶部布局指南不支持自定义转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简短版本:

在 iOS7 中与自定义过渡和 UINavigationController 结合使用时,我遇到了自动布局顶部布局指南的问题.具体来说,顶部布局指南和文本视图之间的约束没有得到遵守.有人遇到过这个问题吗?

I am having a problem with auto layout top layout guide when used in conjunction with custom transition and UINavigationController in iOS7. Specifically, the constraint between the top layout guide and the text view is not being honored. Has anyone encountered this issue?

长版:

我有一个场景,它明确定义了约束(即顶部、底部、左侧和右侧),呈现如下所示的视图:

I have a scene which has unambiguously define constraints (i.e. top, bottom, left and right) that renders a view like so:

但是当我将它与导航控制器上的自定义过渡一起使用时,顶部布局指南的顶部约束似乎关闭并且呈现如下,就好像顶部布局指南位于屏幕顶部,而不是在导航控制器底部:

But when I use this with a custom transition on the navigation controller, the top constraint to the top layout guide seems off and it renders is as follows, as if the top layout guide was at the top of the screen, rather than at the bottom of the navigation controller:

使用自定义过渡时,导航控制器的顶部布局指南"似乎变得混乱.其余的约束正在被正确应用.如果我旋转设备并再次旋转它,一切都会突然正确渲染,因此似乎不是约束定义不正确的问题.同样,当我关闭自定义过渡时,视图会正确呈现.

It would appear that the "top layout guide" with the navigation controller is getting confused when employing the custom transition. The rest of the constraints are being applied correctly. And if I rotate the device and rotate it again, everything is suddenly rendered correctly, so it does not appear to be not a matter that the constraints are not defined properly. Likewise, when I turn off my custom transition, the views render correctly.

话虽如此,当我运行时,_autolayoutTrace 报告 UILayoutGuide 对象受到 AMBIGUOUS LAYOUT 的影响:

Having said that, _autolayoutTrace is reporting that the UILayoutGuide objects suffer from AMBIGUOUS LAYOUT, when I run:

(lldb) po [[UIWindow keyWindow] _autolayoutTrace]

但是这些布局指南在我查看它们时总是被报告为模棱两可,即使我已经确保没有缺少约束(我已经完成了视图控制器的习惯选择并选择了为视图控制器添加缺少的约束"或选择所有控件并对其执行相同操作).

But those layout guides are always reported as ambiguous whenever I look at them even though I've ensured that there are no missing constraints (I've done the customary selecting of view controller and choosing "Add missing constraints for view controller" or selecting all of the controls and doing the same for them).

就我进行过渡的精确程度而言,我在 animationControllerForOperation 方法中指定了一个符合 UIViewControllerAnimatedTransitioning 的对象:

In terms of how precisely I'm doing the transition, I've specified an object that conforms to UIViewControllerAnimatedTransitioning in the animationControllerForOperation method:

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                  animationControllerForOperation:(UINavigationControllerOperation)operation
                                               fromViewController:(UIViewController*)fromVC
                                                 toViewController:(UIViewController*)toVC
{
    if (operation == UINavigationControllerOperationPush)
        return [[PushAnimator alloc] init];

    return nil;
}

@implementation PushAnimator

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

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController* toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    [[transitionContext containerView] addSubview:toViewController.view];
    CGFloat width = fromViewController.view.frame.size.width;

    toViewController.view.transform = CGAffineTransformMakeTranslation(width, 0);

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        fromViewController.view.transform = CGAffineTransformMakeTranslation(-width / 2.0, 0);
        toViewController.view.transform = CGAffineTransformIdentity;
    } completion:^(BOOL finished) {
        fromViewController.view.transform = CGAffineTransformIdentity;
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end

我还对上述内容进行了再现,设置了视图的 frame 而不是 transform,结果相同.

I've also done a rendition of the above, setting the frame of the view rather than the transform, with the same result.

我还尝试通过调用 layoutIfNeeded 手动确保重新应用约束.我也试过 setNeedsUpdateConstraintssetNeedsLayout

I've also tried manually make sure that the constraints are re-applied by calling layoutIfNeeded. I've also tried setNeedsUpdateConstraints, setNeedsLayout, etc.

最重要的是,有没有人成功地将导航控制器的自定义转换与使用顶部布局指南的约束结合起来?

Bottom line, has anyone successfully married custom transition of navigation controller with constraints that use top layout guide?

推荐答案

我通过修复 topLayoutGuide 的高度约束解决了这个问题.调整 edgesForExtendedLayout 对我来说不是一个选项,因为我需要目标视图来覆盖导航栏,而且还需要能够使用 topLayoutGuide 布局子视图.

I solved this by fixing the height constraint of the topLayoutGuide. Adjusting edgesForExtendedLayout wasn't an option for me, as I needed the destination view to underlap the navigation bar, but also to be able to layout subviews using topLayoutGuide.

直接查看play中的constraints,发现iOS在topLayoutGuide中添加了一个高度约束,其值等于导航控制器导航栏的高度.除了,在 iOS 7 中,使用自定义动画过渡会留下高度为 0 的约束.他们在 iOS 8 中修复了这个问题.

Directly inspecting the constraints in play shows that iOS adds a height constraint to the topLayoutGuide with value equal to the height of the navigation bar of the navigation controller. Except, in iOS 7, using a custom animation transition leaves the constraint with a height of 0. They fixed this in iOS 8.

这是我想出的解决约束的解决方案(它在 Swift 中,但等效的应该在 Obj-C 中工作).我已经测试过它适用于 iOS 7 和 8.

This is the solution I came up with to correct the constraint (it's in Swift but the equivalent should work in Obj-C). I've tested that it works on iOS 7 and 8.

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
    let fromView = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view
    let destinationVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
    destinationVC.view.frame = transitionContext.finalFrameForViewController(destinationVC)
    let container = transitionContext.containerView()
    container.addSubview(destinationVC.view)

    // Custom transitions break topLayoutGuide in iOS 7, fix its constraint
    if let navController = destinationVC.navigationController {
        for constraint in destinationVC.view.constraints() as [NSLayoutConstraint] {
            if constraint.firstItem === destinationVC.topLayoutGuide
                && constraint.firstAttribute == .Height
                && constraint.secondItem == nil
                && constraint.constant == 0 {
                constraint.constant = navController.navigationBar.frame.height
            }
        }
    }

    // Perform your transition animation here ...
}

这篇关于导航控制器顶部布局指南不支持自定义转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆