【问题标题】:How to solve this problem with custom transition in iOS?如何通过 iOS 中的自定义转换来解决这个问题?
【发布时间】:2018-11-17 21:55:24
【问题描述】:

我构建了一个类来实现视图控制器之间的循环转换。当我点击按钮导航到另一个视图控制器时,一个圆圈开始从按钮开始增长,直到它用新控制器填充屏幕。当我关闭视图控制器时,我预计这个圆圈会缩小回原来的位置。它也在工作。唯一的问题是,在关闭过程中,当圆圈缩小时,屏幕背面是完全黑色的,并且在动画完成后,新的 viewController 会突然出现。

以下是一些效果图:

自定义类的代码如下:

class customTransition: NSObject, UIViewControllerAnimatedTransitioning{

var duration: TimeInterval = 0.5
var startPoint = CGPoint.zero

var circle = UIView()

var circleColor = UIColor.white
enum transitMode: Int {
    case presenting, dismissing
}

var transitionMode: transitMode = .presenting

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

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    let container = transitionContext.containerView
    guard let to = transitionContext.view(forKey: UITransitionContextViewKey.to) else {return}
    guard let from = transitionContext.view(forKey: UITransitionContextViewKey.from) else {return}

    circleColor = to.backgroundColor ?? UIColor.white

    if transitionMode == .presenting {
        to.translatesAutoresizingMaskIntoConstraints = false
        to.center = startPoint

        circle = UIView()
        circle.backgroundColor = circleColor
        circle.frame = getFrameForCircle(rect: to.frame)
        circle.layer.cornerRadius = circle.frame.width / 2
        circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
        circle.alpha = 0


        circle.addSubview(to)

        to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
        to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
        to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
        to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

        container.addSubview(circle)

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
            self.circle.center = from.center
            self.circle.transform = CGAffineTransform.identity
            self.circle.alpha = 1

        }) { (sucess) in

            transitionContext.completeTransition(sucess)

        }

    } else if transitionMode == .dismissing {


        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
            self.circle.center = self.startPoint
            self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
            self.circle.alpha = 0

        }) { (sucess) in
            transitionContext.completeTransition(sucess)
        }
    }
}




func getFrameForCircle(rect: CGRect) -> CGRect{
    let width = Float(rect.width)
    let height = Float(rect.height)

    let diameter = CGFloat(sqrtf(width * width + height * height))

    let x: CGFloat = rect.midX - (diameter / 2)
    let y: CGFloat = rect.midY - (diameter / 2)

   return CGRect(x: x, y: y, width: diameter, height: diameter)
}



}

以及实现...

    let circularTransition = customTransition()

对当前视图控制器的调用...我尝试设置secondVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext,但是当我设置此行时,它完全忽略了动画过渡,我不知道为什么... `

 @objc func handlePresent(sender: UIButton){
    let secondVC = nextVC()
    secondVC.transitioningDelegate = self
    present(secondVC, animated: true, completion: nil)

}

委托方法:

  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    circularTransition.startPoint = presentButton.center
    circularTransition.transitionMode = .presenting
    return circularTransition
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    circularTransition.transitionMode = .dismissing
    circularTransition.startPoint = presentButton.center

    return circularTransition
}

我在这里缺少什么?有什么建议么? 没有使用故事板,只使用代码。

【问题讨论】:

  • 我认为您看到这个问题是因为您使用的是present 而不是navigationController。我建议尝试使用 navigationController 来推送/弹出 ViewController 并在 ViewController 出现时应用您的动画。因此,您可以在没有动画的情况下从 NavController 推送/弹出 VC。但是,VC 本身会在出现缩小或增长到/从一个圆圈时应用您想要的动画
  • 您展示了在第一个控制器上显示第二个控制器的代码。还请添加您如何关闭第 2 次并尝试转换回第 1 次。

标签: ios swift uiviewanimationtransition


【解决方案1】:

如果不使用navigationController,则需要在presentedviewController中使用.custom模式。

 import UIKit

            class TransViewController: UIViewController {

                override func viewDidLoad() {
                    super.viewDidLoad()

                    // Do any additional setup after loading the view.
                }
                 let circularTransition = customTransition()

                @IBOutlet var presentButton : UIButton!

             @IBAction   func handlePresent(sender: UIButton){

                if let secondVC = storyboard?.instantiateViewController(withIdentifier: "next"){
                    secondVC.modalPresentationStyle = .custom
                    secondVC.transitioningDelegate = self
                    present(secondVC, animated: true, completion: nil)
                }
                }

            }


            class BackViewController: UIViewController {

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

            }

            extension TransViewController: UIViewControllerTransitioningDelegate {

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

                    circularTransition.startPoint = presentButton.center
                    circularTransition.transitionMode = .presenting
                    return circularTransition
                }

                func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                    circularTransition.transitionMode = .dismissing
                    circularTransition.startPoint = presentButton.center

                    return circularTransition
                }

            }

如果没有 from 或 to view,我们使用 from 和 to view from containsView。

   func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    let container = transitionContext.containerView
    var to : UIView!
    var from : UIView!
    to = transitionContext.view(forKey: UITransitionContextViewKey.to)
    if to == nil {to = container}
    from = transitionContext.view(forKey: UITransitionContextViewKey.from)
    if from == nil {from = container}

其余相同:

 circleColor = to.backgroundColor ?? UIColor.white

    if transitionMode == .presenting {
        to.translatesAutoresizingMaskIntoConstraints = false
        to.center = startPoint

        circle = UIView()
        circle.backgroundColor = circleColor
        circle.frame = getFrameForCircle(rect: to.frame)
        circle.layer.cornerRadius = circle.frame.width / 2
        circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
        circle.alpha = 0


        circle.addSubview(to)

        to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
        to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
        to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
        to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

        container.addSubview(circle)

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
            self.circle.center = from.center
            self.circle.transform = CGAffineTransform.identity
            self.circle.alpha = 1

        }) { (sucess) in

            transitionContext.completeTransition(sucess)

        }

    } else if transitionMode == .dismissing {


        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
            self.circle.center = self.startPoint
            self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
            self.circle.alpha = 0

        }) { (sucess) in
            transitionContext.completeTransition(sucess)
        }
    }
}  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    相关资源
    最近更新 更多