如何在iOS中通过自定义转换解决此问题?
我构建了一个类来实现视图控制器之间的循环转换。当我点击按钮导航到另一个视图控制器时,一个圆圈从按钮开始增长,直到它用新的控制器填满屏幕。当我关闭视图控制器时,我希望这个圆缩小回原始位置。它也在工作。唯一的问题是,当“关闭”正在进行时,圆圈收缩时的屏幕背面完全是黑色的,动画完成后,新的viewController突然出现 以下是一些效果照片: 以下是自定义类的代码:如何在iOS中通过自定义转换解决此问题?,ios,swift,uiviewanimationtransition,Ios,Swift,Uiviewanimationtransition,我构建了一个类来实现视图控制器之间的循环转换。当我点击按钮导航到另一个视图控制器时,一个圆圈从按钮开始增长,直到它用新的控制器填满屏幕。当我关闭视图控制器时,我希望这个圆缩小回原始位置。它也在工作。唯一的问题是,当“关闭”正在进行时,圆圈收缩时的屏幕背面完全是黑色的,动画完成后,新的viewController突然出现 以下是一些效果照片: 以下是自定义类的代码: class customTransition: NSObject, UIViewControllerAnimatedTransit
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
但是当我设置这一行时,它完全忽略了动画转换,我不知道为什么。。。
`
委托方法:
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
}
我错过了什么?有什么建议吗?
没有使用故事板,只需编写代码。如果不使用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
}
}
如果没有“从”或“到”视图,则使用“从”和“到”视图
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)
}
}
}
我认为您看到这个问题是因为您使用的是
present
,而不是。我建议尝试使用navigationController来推/弹出ViewController,并在显示ViewController时应用动画。因此,您可以在没有动画的情况下从NavController推/弹出VC。但是,VC本身会在显示第二个控制器在第一个控制器上的循环显示代码时应用所需的动画。还请添加您如何取消第二个并尝试转换回第一个。
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)
}
}
}