TabBar 图标对选择的反弹效果就像 Swift 中的 Twitter 应用程序

Posted

技术标签:

【中文标题】TabBar 图标对选择的反弹效果就像 Swift 中的 Twitter 应用程序【英文标题】:TabBar icon bounce effect on selection like a Twitter app in Swift 【发布时间】:2017-02-09 11:46:31 【问题描述】:

当我点击其中一个时,如何创建类似于 Twitter 应用程序的标签栏图标反弹效果?看起来它缩小了,然后又恢复正常了。

谢谢。

【问题讨论】:

可以通过实现自定义的 TabBarViewController 和 TabBarView 来实现 @GonjiDev 谢谢。但我该怎么做呢?你能给我看一些sn-p吗? 【参考方案1】:

这是一个对我有用的非常简单的解决方案。子类化UITabBarController 并覆盖func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem)

class AnimatedTabBarController: UITabBarController 

    private var bounceAnimation: CAKeyframeAnimation = 
        let bounceAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
        bounceAnimation.values = [1.0, 1.4, 0.9, 1.02, 1.0]
        bounceAnimation.duration = TimeInterval(0.3)
        bounceAnimation.calculationMode = CAAnimationCalculationMode.cubic
        return bounceAnimation
    ()

    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) 
        // find index if the selected tab bar item, then find the corresponding view and get its image, the view position is offset by 1 because the first item is the background (at least in this case)
        guard let idx = tabBar.items?.index(of: item), tabBar.subviews.count > idx + 1, let imageView = tabBar.subviews[idx + 1].subviews.first as? UIImageView else 
            return
        

        imageView.layer.add(bounceAnimation, forKey: nil)
    

结果是这样的

【讨论】:

我遇到了问题,我有 5 个标签栏项目,但是我如何编写上面的代码以仅在单击时为特定的标签项目设置动画【参考方案2】:

我知道怎么做。轻松玩!!! 假设有 5 个标签栏项目,标签是 0,1,2,3,4,那么在你的标签栏控制器中:

 class xxxVC: UITabBarController 

        var storedImageViewArr:[UIImageView?] = []

    private var times = [Int].init(repeating: 0, count: 5)
    private var tempTimes = [Int].init(repeating: 0, count: 5)

     let bounceAnimation = CAKeyframeAnimation(keyPath: "transform.scale")   

    override func viewDidLoad() 
            super.viewDidLoad()

      // create image views
     getImageView()

    //set path
        setPath()
    //xxxVC class over line

    //custom functions
    extension xxxVC

    fileprivate func getImageView()
times[0] = 1
            storedImageViewArr = [0,1,2,3,4].map (offset) -> UIImageView in
    let tempImageView = self.tabBar.subviews[offset].subviews.first as! UIImageView
    tempImageView.contentMode = .center
    return tempImageView
            

    fileprivate func setPath()

            bounceAnimation.values = [1.0 ,0.6, 0.9, 1.15, 0.95, 1.02, 1.0]
            bounceAnimation.duration = TimeInterval(0.5)
            bounceAnimation.calculationMode = kCAAnimationCubic
        
    

    //UITabBarControllerDelegate
    extension xxxVC

        override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) 

    //the arr in this count is sure, so it costs O(1)
    if times[item.tag] == 0
            setAnimation(at: item.tag)
            times = tempTimes
            times[item.tag] += 1;return
        
    
    

所以,你可以做到。

【讨论】:

拜托了!给我加星标! setAnimation 方法在您的 sn-p 中丢失【参考方案3】:

嘿,这不是完美的代码,但应该让您了解如何实现自定义 TabBarViewController。我没有写视图布局部分,所以你应该处理它,并且选项卡项动画也不在这里。

class TabBarViewController: UIViewController, TabBarViewDelegate 

    private var containerView: UIView!
    private var tabBar: TabBarView!

    var selectedTabIndex: Int! 
        didSet 
            if oldValue != nil && oldValue != selectedTabIndex 
                let previousVc = childViewControllers[oldValue]
                previousVc.beginAppearanceTransition(false, animated: false)
                previousVc.view.removeFromSuperview()
                previousVc.endAppearanceTransition()
            

            let vc = childViewControllers[selectedTabIndex]
            vc.beginAppearanceTransition(true, animated: false)
            containerView.addSubview(vc.view)
            vc.endAppearanceTransition()
        
    

    override func loadView() 
        let viewControllers = [YourViewController1(), YourViewController2()]

        containerView = UIView()

        tabBar = TabBarView(numberOfTabs: viewControllers.count)
        tabBar.delegate = self

        viewcontrollers.forEach 
            addChildViewController($0)
            $0.didMove(toParentViewController: self)
        

        view = UIView()
        view.addSubview(containerView)
        view.addSubview(tabBar)

        selectedTabIndex = 0
    

    func didSelect(tab: Int) 
        if selectedTabIndex != tab 
            selectedTabIndex = tab
        
    


protocol TabBarViewDelegate: class 
    func didSelect(tab: Int)


class TabBarView: UIView 

    private let tabs: [TabBarItemView]

    weak var delegate: TabBarViewDelegate? 
        didSet 
            tabs.forEach 
                $0.delegate = delegate
            
        
    

    init(numberOfTabs: Int) 
        let tabs = (0...numberOfTabs).map(TabBarItemView(index: $0))
        super.init(frame: .zero)
        let tabsStackView = UIStackView(arrangedSubviews: tabs) //.horizontal axis
        addSubview(tabsStackView)
    


class TabBarItemView: UIView 

    weak var delegate: TabBarViewDelegate?

    private let index: Int
    private let imageView = UIImageView(image: UIImage(named: ""))

    init(index: Int) 
        self.index = index
        super.init(frame: .zero)

        let tap = UITapGestureRecognizer()
        tap.addTarget(self, action: #selector(onSelected))
        gestureRecognizers = [tap]
        addSubview(imageView)
    

    @objc private func onSelected() 
        //animate imageView
        delegate?.didSelect(tab: index)
    

【讨论】:

以上是关于TabBar 图标对选择的反弹效果就像 Swift 中的 Twitter 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

(Swift) 选择 tabBar 颜色?

用不同的颜色填充iOS Tabbar图标[重复]

是否可以在不着色图标的情况下为 TabBar 着色?

swift 用UIBezierPath自定义中间突出的tabbar

TabBar图标定位[重复]

选择和未选择状态的反应导航中的不同tabBar图标?