【问题标题】:iOS: UILabel is not centered while expanding view with UIViewControllerTransitioningDelegateiOS:使用 UIViewControllerTransitioningDelegate 扩展视图时,UILabel 未居中
【发布时间】:2019-06-09 22:22:14
【问题描述】:

我试图在点击按钮时以模态方式呈现一个视图,该视图首先与按钮具有相同的框架,然后扩展为全屏,所有这些都使用UIViewControllerTransitioningDelegate

这是我的代码:

可扩展基础

class ExpandableBase: UIViewController {

    var senderFrame: CGRect = .zero    
    @IBOutlet weak var fullScreenPopupView: UIView?

    @IBAction func dismiss() {
        self.dismiss(animated: true, completion: nil)
    }

}

过渡委托扩展

extension ExpandableBase: UIViewControllerTransitioningDelegate {

    public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return ExpandableBasePresenter()
    }

    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return ExpandableBaseDismisser()
    }

}  

private final class ExpandableBasePresenter: NSObject, UIViewControllerAnimatedTransitioning {

    public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.8
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let toViewController: ExpandableBase = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! ExpandableBase
        let duration = self.transitionDuration(using: transitionContext)
        let containerView = transitionContext.containerView
        toViewController.view.frame = containerView.frame
        containerView.addSubview(toViewController.view)
        let finishFrame = toViewController.fullScreenPopupView?.frame
        toViewController.fullScreenPopupView?.frame = toViewController.senderFrame
        UIView.animate(withDuration: duration, delay: 0.3, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: .layoutSubviews, animations: {
            toViewController.fullScreenPopupView?.frame = finishFrame!
        }) { result in
            transitionContext.completeTransition(result)
        }
    }

}

private final class ExpandableBaseDismisser: NSObject, UIViewControllerAnimatedTransitioning {

    public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.4
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let fromViewController: ExpandableBase = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! ExpandableBase
        let duration = self.transitionDuration(using: transitionContext)
        UIView.animate(withDuration: duration, delay: 0.1, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: .layoutSubviews, animations: {
            fromViewController.fullScreenPopupView?.frame = fromViewController.senderFrame
        }) { result in
            transitionContext.completeTransition(result)
        }
    }

}

使用它的简单视图,显示标签和关闭按钮:

final class ExpandableSimpleView: ExpandableBase {

    init(from initialFrame: CGRect) {
        super.init(nibName: "ExpandableSimpleView", bundle: .main)
        self.senderFrame = initialFrame
        self.transitioningDelegate = self
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("NOPE")
    }

    static func present(fromInitialFrame initialFrame: CGRect) {
        let expandableSimpleView = ExpandableSimpleView(from: initialFrame)
        expandableSimpleView.modalPresentationStyle = .overCurrentContext  
        AppDelegateTopMostViewController.present(expandableSimpleView, animated: true, completion: nil)
        //AppDelegateTopMostViewController is a global reference to the top-most view controller of the app            
    }

}

这里是对应的XIB:

以及我如何从父视图控制器呈现它:

@IBAction func openSimpleView(_ sender: UIButton) {
    ExpandableSimpleView.present(fromInitialFrame: sender.frame)
}

这里有一些屏幕截图显示了这个视图是如何扩展的:

虽然视图扩展得很好,但标签并没有像应有的那样居中。我不明白为什么。

感谢您的帮助。

编辑:按照马特的回答,我对animateTransition 的演示者进行了以下更改。

    toViewController.fullScreenPopupView!.transform = 

    toViewController.fullScreenPopupView!.transform.scaledBy(x: toViewController.senderFrame.width / toViewController.view.bounds.width, y: toViewController.senderFrame.height / toViewController.view.bounds.height)
    UIView.animate(withDuration: duration, delay: 0, options: [.allowUserInteraction], animations: {
        toViewController.fullScreenPopupView!.transform = .identity
    }, completion: nil)

现在动画很好,但我面临另一个问题:视图中的按钮不再可点击。

【问题讨论】:

    标签: ios autolayout uiviewanimationtransition


    【解决方案1】:

    你的动画是错误的。不要从一个小框架开始并为框架的扩展设置动画。从一个小的变换开始(例如,x 和 y 的比例值为 0.1)并扩展变换(到 .identity)。

    【讨论】:

    • 您好,谢谢您的回答,我明白了。然而,虽然动画现在很好,但我面临另一个问题:我的视图上的“关闭”按钮不再可点击。请查看我的帖子的编辑。
    • 这是一个错误的程序。我已经正确回答了你的问题,并帮助了你。所以你会怎么做?而不是奖励我,单击复选标记以接受我的答案并关闭问题,您只需“免费”获得我的帮助并更改问题以使我的答案错误。请撤消您对答案的编辑,接受我的回答,如果您现在还有其他问题,请提出不同的问题
    • 在您更改动画之前按钮是否可点击?
    【解决方案2】:

    缩小或扩大父视图并没有错。

    您不必为实际视图设置动画。您可以创建和删除临时视图。隐藏实际视图并在移除过程中显示它。

    我建议您单独为 UILabel 设置动画。它不必缩小或增长。它只需要保持静止。在原件上放置一个临时的 UILabel,隐藏原件,然后执行动画。在删除期间反转该过程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 2018-10-23
      相关资源
      最近更新 更多