使用自动布局将模态视图居中 [英] Centering Modal View with Autolayout

查看:82
本文介绍了使用自动布局将模态视图居中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在展示一个使用presentViewController和自定义modalPresentationStyle的UIViewController,以实现Facebook POP动画过渡.

I'm presenting a UIViewController using presentViewController and a custom modalPresentationStyle, in an effort to implement a Facebook POP animated transition.

模态视图本身是完全动态的,使用代码中的自动布局"约束定义.没有xib/storyboard来支持模态.

The modal view itself is completely dynamic, defined using Autolayout constraints in code. There is no xib/storyboard to back the modal.

我无法将模式视图显示在屏幕中央!自动布局是不够的,因为没有可添加约束的超级视图!

我的演示代码如下(摘自FB POP代码示例):

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    UIView *fromView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;
    fromView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
    fromView.userInteractionEnabled = NO;

    UIView *dimmingView = [[UIView alloc] initWithFrame:fromView.bounds];
    dimmingView.backgroundColor = [UIColor colorWithRed:(24/255.0) green:(42/255.0) blue:(15/255.0) alpha:1.0];
    dimmingView.layer.opacity = 0.0;

    UIView *toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
    toView.frame = CGRectMake(0,
                              0,
                              CGRectGetWidth(transitionContext.containerView.bounds) - 104.f,
                              CGRectGetHeight(transitionContext.containerView.bounds) - 320.f);
    toView.center = CGPointMake(transitionContext.containerView.center.x, -transitionContext.containerView.center.y);

    [transitionContext.containerView addSubview:dimmingView];
    [transitionContext.containerView addSubview:toView];

    POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    positionAnimation.toValue = @(transitionContext.containerView.center.y);
    positionAnimation.springBounciness = 10;
    [positionAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
        [transitionContext completeTransition:YES];
    }];

    POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
    scaleAnimation.springBounciness = 20;
    scaleAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(1.2, 1.4)];

    POPBasicAnimation *opacityAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity];
    opacityAnimation.toValue = @(0.2);

    [toView.layer pop_addAnimation:positionAnimation forKey:@"positionAnimation"];
    [toView.layer pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"];
    [dimmingView.layer pop_addAnimation:opacityAnimation forKey:@"opacityAnimation"];
}

这很漂亮,但是我需要实际的视图大小是动态的(有时模态将有四行文本和两个按钮,等等).为此,我需要在VC子类中设置translationsAutoresizingMaskIntoConstraints = NO.显然,这会抵消我在演示动画师中所做的帧居中.

This works beautifully, but I need the actual view size to be dynamic (sometimes the modal will have four lines of text and two buttons, etc). To accomplish this, I need to set translatesAutoresizingMaskIntoConstraints=NO in the VC subclass. This obviously negates the frame centering I'm doing in the presentation animator.

最终结果是粘贴在屏幕左边缘的模态;奇怪的是,它在垂直方向上居中,但不在水平方向上居中.从视觉上看,它看起来像这样(对黑方块,出于法律目的,我不得不这样做):

The end result is a modal that's stuck to the left edge of the screen; curiously, it centers itself vertically, but not horizontally. Visually, it looks something like this (pardon the black squares, I had to do it for legal purposes):

显而易见的解决方案是添加一个使视图居中的视图约束.没问题吧?

The obvious solution would be to add a view constraint that centers the view. No problem, right?

但是我应该在哪里添加它? view.superview为零;没有监督.我尝试创建一个自定义的"superview"属性并进行设置,但是autolayout不知道如何处理其视图层次结构之外的视图(当前的vc).这是我的视图层次结构的样子,带有注释:

But where do I add it? view.superview is nil; there is no superview. I tried creating a custom 'superview' property and setting it, but autolayout doesn't know how to handle a view that's outside of its view hierarchy (the presenting vc). This is what my view hierarchy looks like, annotated:

您显然不应该直接访问UITransitionView.对UIWindow的约束无效.

You're apparently not supposed to access the UITransitionView directly. Constraints on the UIWindow have no effect.

有人有什么建议吗?你们如何处理这种事情?

Does anyone have any advice? How do you guys handle this sort of thing?

推荐答案

您可以通过animateTranisition方法以编程方式将containerView的居中约束添加到toView:

You can programmatically add a centering constraint from containerView to toView in your animateTranisition method:

(在Swift中,但您应该可以理解...)

(in Swift, but you should be able to get the idea...)

containerView.addSubview(toView)

let centerXLayoutConstraint = NSLayoutConstraint(item: toView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: containerView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
let centerYLayoutConstraint = NSLayoutConstraint(item: toView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: containerView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)

containerView.addConstraint(centerXLayoutConstraint)
containerView.addConstraint(centerYLayoutConstraint)

当我尝试此操作时,我还向toView添加了宽度和高度限制,以相对于containerView调整其大小.没问题-没问题.

When I tried this, I also added width and height constraints to toView to size it relative to containerView. It worked -- no problem.

我认为它也应该与自调整大小的toView一起使用.您可能必须在toView类中重写internalSize和/或尝试强制其更新其约束.

I think it should work with a self-sizing toView as well. You might have to override intrinsicSize in your toView class and/or play around with forcing it to update its constraints.

这篇关于使用自动布局将模态视图居中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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