我有一个基于导航的应用程序,我想更改推送和弹出动画的动画.我该怎么做?

Edit 2018

这个问题有很多答案,而且已经有一段时间了,我已经重新 Select 了我认为最相关的答案.如果有人不这么认为,请在 comments 中告诉我

推荐答案

如何在基于导航的应用程序中更改推送和弹出动画.

Preamble:

假设您是iOS开发的新手.令人困惑的是,苹果提供了两个易于使用的过渡.它们是:"交叉淡入淡出"和"翻转".

当然,"交叉淡入淡出"和"翻转"是没用的.他们从来没有用过.没有人知道为什么苹果提供了这两个无用的过渡!

因此:

假设你想做an ordinary, common, transition个,比如"幻灯片".那样的话,you have to do a HUGE amount of work!美元.

这项工作,在这篇文章中有解释.

我只想重复一遍:

令人惊讶的是:在iOS中,如果你想要simplest, most common, everyday transitions(比如普通的幻灯片),你必须实现full custom transitionall the work.

以下是如何做到这一点...

1. You need a custom UIViewControllerAnimatedTransitioning

  1. 你需要一个你自己的波波,比如popStyle.(它是突然打开还是突然熄灭?)

  2. 你必须包括transitionDuration(琐碎的)和主呼叫animateTransition

  3. 事实上,你可以为inside animateTransition编写两个不同的 routine .一个是推,一个是流行音乐.可能是animatePushanimatePop.在animateTransition之内,只需将popStyle分支到两个 routine

  4. 下面的例子做了一个简单的移过go /移走

  5. 在你的animatePushanimatePop套路中.你可以得到"从视图"和"到视图".(如何做到这一点,如代码示例所示.)

  6. 101addSubview看新的"收件人"视图.

  7. 在你的动画片结束时,你101拨打completeTransition

所以.

  class SimpleOver: NSObject, UIViewControllerAnimatedTransitioning {
        
        var popStyle: Bool = false
        
        func transitionDuration(
            using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.20
        }
        
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            
            if popStyle {
                
                animatePop(using: transitionContext)
                return
            }
            
            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
            
            let f = transitionContext.finalFrame(for: tz)
            
            let fOff = f.offsetBy(dx: f.width, dy: 55)
            tz.view.frame = fOff
            
            transitionContext.containerView.insertSubview(tz.view, aboveSubview: fz.view)
            
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    tz.view.frame = f
            }, completion: {_ in 
                    transitionContext.completeTransition(true)
            })
        }
        
        func animatePop(using transitionContext: UIViewControllerContextTransitioning) {
            
            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
            
            let f = transitionContext.initialFrame(for: fz)
            let fOffPop = f.offsetBy(dx: f.width, dy: 55)
            
            transitionContext.containerView.insertSubview(tz.view, belowSubview: fz.view)
            
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    fz.view.frame = fOffPop
            }, completion: {_ in 
                    transitionContext.completeTransition(true)
            })
        }
    }

然后...

2.在您的视图控制器中使用它.

注意:奇怪的是,你在"第一"视图控制器中.(下面的那个)

用你在top上弹出的那个,做nothing.轻松点.

所以你们班...

class SomeScreen: UIViewController {
}

变成了...

class FrontScreen: UIViewController,
        UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {
    
    let simpleOver = SimpleOver()
    

    override func viewDidLoad() {
        
        super.viewDidLoad()
        navigationController?.delegate = self
    }

    func navigationController(
        _ navigationController: UINavigationController,
        animationControllerFor operation: UINavigationControllerOperation,
        from fromVC: UIViewController,
        to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        
        simpleOver.popStyle = (operation == .pop)
        return simpleOver
    }
}

就这样.

一如往常,一如往常,一如往常.推动...

let n = UIStoryboard(name: "nextScreenStoryboardName", bundle: nil)
          .instantiateViewController(withIdentifier: "nextScreenStoryboardID")
          as! NextScreen
navigationController?.pushViewController(n, animated: true)

要弹出它,如果您愿意,只需在下一个屏幕上这样做就可以了:

class NextScreen: TotallyOrdinaryUIViewController {
    
    @IBAction func userClickedBackOrDismissOrSomethingLikeThat() {
        
        navigationController?.popViewController(animated: true)
    }
}

哎哟.


3. Also enjoy the other answers on this page which explain how to override AnimatedTransitioning !

滚动到@AlanZeino和@Elias Answer了解更多关于如何在iOS应用程序中使用AnimatedTransitioning的讨论!

Ios相关问答推荐

iPhone:iOS 17.4中没有气压数据

Xamarin Forms CustomPin iOS Render

当操作修改查看条件时,按钮不重复

如何根据SWIFT中的按钮点击更新文本值

如何在不将应用程序留在SwiftUI上的情况下更改语言?

iOS应用启动时崩溃问题解决方法-NO_CRASH_STACK-DYLD 4个符号丢失

为什么 Firebase Messaging 配置对于 IOS native 和 Flutter iOS 不同?

Swift Combine:prepend() before share() 阻止初始接收器执行

为什么这个 SwiftUI 状态在作为非绑定参数传递时没有更新?

如何在 SwiftUI 中创建显示当前电池电量的电池徽章

小部件链接有效,但不执行任何操作

具有多个目标的应用程序的动态内容

渲染的海边重定向在物理 iOS 设备上不起作用

SwiftUI 切换语句

UIViewControllerRepresentable 在 Xcode 14 iOS 16 上崩溃

如何设置imageView的圆角半径?

不变违规:应用程序 AwesomeProject 尚未注册使用静态 jsbundle 为 iOS 设备构建时

如何以编程方式切换 UISegmentedControl?

如何防止 iOS 设备上的显示屏变暗和关闭?

从 Swift 转换为 Objective-c 的工具