ViewController 幻灯片动画

ViewController slide animation

我想在 tabswitch[1] 上创建类似 iOS 应用程序 facebook 的动画。我已经尝试开发某种动画,出现的问题是旧视图控制器直接在开关上变得不可见,而不是在新控制器快速滑入时慢慢淡出。

我发现了这个 SO 问题 但是正确标记的解决方案对我来说并不适用(它不是幻灯片,它是淡入淡出过渡)。我还想得到的是向左或向右滑动以切换选项卡的功能。就像在旧版本的 facebook 上一样。

到目前为止我得到的是:

extension TabBarController: UITabBarControllerDelegate  {
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        guard let fromView = selectedViewController?.view,
              let toView = viewController.view else { return false }
        if fromView != toView {
            toView.transform = CGAffineTransform(translationX: -90, y: 0)
            UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: {
                toView.transform = CGAffineTransform(translationX: 0, y: 0)
            })
        }; return true
    }
}

class TabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }
}

如何解决这个问题?


[1] 我非常想从 Facebook 应用程序添加 gif。问题是我不想审查视频,只是想透露太多我的数据。 (即使 fb 已经有了它们)。同样在 youtube 上我没有找到合适的录音。请在 iOS.

的 fb 应用程序中自己尝试

你可以使用下面的思路:https://samwize.com/2016/04/27/making-tab-bar-slide-when-selected/

此外,这里的代码已更新到 Swift 4.1,我还删除了强制展开:

import UIKit

class MyTabBarController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()

        delegate = self
    }
}

extension MyTabBarController: UITabBarControllerDelegate  {
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        guard let tabViewControllers = tabBarController.viewControllers, let toIndex = tabViewControllers.index(of: viewController) else {
            return false
        }
        animateToTab(toIndex: toIndex)
        return true
    }

    func animateToTab(toIndex: Int) {
        guard let tabViewControllers = viewControllers,
            let selectedVC = selectedViewController else { return }

        guard let fromView = selectedVC.view,
            let toView = tabViewControllers[toIndex].view,
            let fromIndex = tabViewControllers.index(of: selectedVC),
            fromIndex != toIndex else { return }


        // Add the toView to the tab bar view
        fromView.superview?.addSubview(toView)

        // Position toView off screen (to the left/right of fromView)
        let screenWidth = UIScreen.main.bounds.size.width
        let scrollRight = toIndex > fromIndex
        let offset = (scrollRight ? screenWidth : -screenWidth)
        toView.center = CGPoint(x: fromView.center.x + offset, y: toView.center.y)

        // Disable interaction during animation
        view.isUserInteractionEnabled = false

        UIView.animate(withDuration: 0.3,
                       delay: 0.0,
                       usingSpringWithDamping: 1,
                       initialSpringVelocity: 0,
                       options: .curveEaseOut,
                       animations: {
                        // Slide the views by -offset
                        fromView.center = CGPoint(x: fromView.center.x - offset, y: fromView.center.y)
                        toView.center = CGPoint(x: toView.center.x - offset, y: toView.center.y)

        }, completion: { finished in
            // Remove the old view from the tabbar view.
            fromView.removeFromSuperview()
            self.selectedIndex = toIndex
            self.view.isUserInteractionEnabled = true
        })
    }
}

因此,您需要子类化 UITabBarController 并且您还必须编写动画部分,您可以调整动画选项(延迟、持续时间等)。

希望对你有所帮助,干杯!

我从没见过 Facebook,所以我不知道动画是什么。但是当标签栏控制器更改其选项卡(子视图控制器)时,您可以拥有任何动画Apple 提供的内置机制,用于将自定义动画添加到视图控制器之间的转换。它叫做自定义过渡动画

Apple 于 2013 年首次引入了此机制。这是他们的视频 link:https://developer.apple.com/videos/play/wwdc2013/218/

我立即在我的应用程序中采用了这一点,我认为这让它们看起来更漂亮了。这是我喜欢的标签栏控制器自定义转换的演示:

真正酷的是,一旦您决定了想要的动画,就可以很容易地进行 交互式 转换(即用手势而不是单击按钮来驱动它) :

现在,您可能会说:好的,但这不是我想要的动画。没问题!一旦掌握了自定义过渡架构的窍门,将动画更改为您喜欢的任何内容就很容易了。在这个变体中,我只是注释掉一行,这样 "old" 视图控制器就不会滑开:

让您的想象力运行尽情发挥吧!采用自定义过渡动画,iOS 想要的方式。

如果你想要 pushViewController 导航的东西,你可以试试这个。

但是,当在 TabBarController 上的选项卡之间切换时,这将不起作用。为此,我会选择@mihai-erős 的解决方案

根据您的喜好更改动画持续时间,并将此 class 分配给您的导航转场,用于幻灯片动画。

class CustomPushSegue: UIStoryboardSegue {

    override func perform() {
        // first get the source and destination view controllers as UIviews so that they can placed in navigation stack

        let sourceVCView = self.source.view as UIView!
        let destinationVCView = self.destination.view as UIView!
        let screenWidth = UIScreen.main.bounds.size.width

        //create the destination view's rectangular frame i.e starting at 0,0 and equal to screenwidth by screenheight
        destinationVCView?.transform = CGAffineTransform(translationX: screenWidth, y: 0)

        //the destinationview needs to be placed on top(aboveSubView) of source view in the app window stack before being accessed by nav stack
        // get the window and insert destination View
        let window = UIApplication.shared.keyWindow
        window?.insertSubview(destinationVCView!, aboveSubview: sourceVCView!)


        // the animation: first remove the source out of screen by moving it at the left side of it and at the same time place the destination to source's position
        // Animate the transition.
        UIView.animate(withDuration: 0.3, animations: { () -> Void in
            sourceVCView?.transform = CGAffineTransform(translationX: -screenWidth,y: 0)
            destinationVCView?.transform = CGAffineTransform.identity

        }, completion: { (Finished) -> Void in
            self.source.present(self.destination, animated: false, completion: nil)
        }) 
    }
}