【问题标题】:CGAffineTransform messing up ViewFrameCGAffineTransform 弄乱了 ViewFrame
【发布时间】:2020-01-16 13:03:48
【问题描述】:

我有一个UIViewControllerAnimatedTransitioning,其中一个动画是使用CGAffineTransform 的比例

toView.frame.origin.y = containerView.frame.size.height - toView.frame.height
fromView.transform = CGAffineTransform(scaleX: 0.96, y: 0.94)
fromView.frame = fromView.frame.offsetBy(dx: 0, dy: self.topOffset)

这让我的框架从(0.0, 0.0, 375.0, 667.0) 到(7.5, 20.00999999999999, 360.0, 626.98),然后在返回的路上:

toView.transform = CGAffineTransform.identity
toView.frame = toView.frame.offsetBy(dx: 0, dy: -self.topOffset)
fromView.frame.origin.y = containerView.frame.size.height

问题是:框架没有回到原来的位置,而是搞砸了,现在我得到:0.0, -5.684341886080802e-14, 375.0, 667.0000000000001),主要问题当然是 y 定位。

请注意 self.topOffset 的值为 0,我已尝试删除此行,但没有任何结果。

第一个 sn-p 中的 fromView 是第二个中的 toView。

如果要查看该函数的完整代码:

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromViewController = transitionContext.viewController(forKey: .from),
            let toViewController = transitionContext.viewController(forKey: .to),
            let toView = toViewController.view,
            let fromView = fromViewController.view,
            let containerView = containerView else { return }


        let isPresenting = fromViewController == presentingViewController
        if isPresenting {
            toView.frame.origin.y = fromView.frame.size.height
        }

        UIView.animate(withDuration: transitionDuration(using: transitionContext),
                       delay: 0,
                       usingSpringWithDamping: 1,
                       initialSpringVelocity: 0,
                       options: .curveEaseInOut,
                       animations: {
            if isPresenting {
                toView.frame.origin.y = containerView.frame.size.height - toView.frame.height
                fromView.transform = CGAffineTransform(scaleX: 0.96, y: 0.94)
                fromView.frame = fromView.frame.offsetBy(dx: 0, dy: self.topOffset)
            }
            else {
                toView.transform = CGAffineTransform.identity
                toView.frame = toView.frame.offsetBy(dx: 0, dy: -self.topOffset)
                fromView.frame.origin.y = containerView.frame.size.height
            }
        }) { (finished) in
            if finished {
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            }
        }
    }

顺便说一句,保留变量的初始值并在之后设置它可以解决问题,但这似乎是一种解决方法而不是解决方案。我想了解它发生的原因以及是否有更好的方法。

【问题讨论】:

    标签: swift core-animation uiviewanimation cgaffinetransform uiviewanimationtransition


    【解决方案1】:

    这是我认为可能是错误的。来自 UIView 框架上的Docs,

    如果变换属性不是恒等变换,则值为 此属性未定义,因此应忽略。

    你不应该在设置转换后使用 frame 属性。相反,如文档中所述,

    对此属性的更改可以设置动画。但是,如果变换 属性包含一个非恒等变换,帧的值 属性未定义,不应修改。在这种情况下, 使用 center 属性重新定位视图并调整大小 改为使用 bounds 属性。

    所以

    fromView.frame = fromView.frame.offsetBy(dx: 0, dy: self.topOffset)
    

    需要修改为

    fromView.center = fromView.frame.center + self.topOffset
    fromView.frame = fromView.frame.bounds
    

    但我认为我们不需要修改 toView 代码,因为我们在设置框架之前将转换设置为 Identity。


    根据上面所说,解决问题的方法是修改第一个块:

    toView.frame.origin.y = containerView.frame.size.height - toView.frame.height
    fromView.transform = CGAffineTransform(scaleX: 0.96, y: 0.94)
    fromView.frame = fromView.frame.offsetBy(dx: 0, dy: self.topOffset)
    

    到

    toView.frame.origin.y = containerView.frame.size.height - toView.frame.height
    fromView.frame = fromView.frame.offsetBy(dx: 0, dy: self.topOffset)
    fromView.transform = CGAffineTransform(scaleX: 0.96, y: 0.94)
    

    基本上在应用变换之前进行帧重新定位。

    【讨论】:

    • 所以基本上你的意思是我不能在应用任何类型的变换之后修改框架,根据这个理论,我做了一个测试并将第一个块第三行与第二个反转并像一种魅力。谢谢!!!顺便说一句,我会用我所做的来编辑你的答案。
    猜你喜欢
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-22
    • 2014-07-20
    相关资源
    最近更新 更多