如何为标签栏的项目设置动画

How to animate tab bar's items

在我的 Swift 应用程序中,我有这个 class 可以处理 UITabBar

class CustomTabBar: UITabBar {
    override func awakeFromNib() {
        super.awakeFromNib()
    }
}

如何在用户点击项目时为项目设置动画? 我的意思是 CGAffine(scaleX: 1.1, y: 1.1) 那么如何为标签栏的项目设置动画?

由于 UITabBarItem 不是 UIView 的子类,而是 NSObject 的子类,因此没有直接的方法在点击时为项目设置动画。

您要么必须挖掘属于该项目的 UIView 并为其设置动画,要么创建一个自定义标签栏。

Here are some ideas for digging up the UIView. And here for example 如何在点击项目时触发。但要非常小心这种方法:

  • Apple 可能会更改 UITabBar 实现,这可能会破坏这一点。
  • 您可能会干扰 iOS 动画并获得奇怪的效果。

顺便说一下,没有必要继承 UITabBar。实施 UITabBarDelegate 就是您所需要的。

我实际上建议您坚持使用标准的 UITabBar 行为和外观选项,然后再解决这个问题,或者根本不考虑。像这样的事情可以消耗你的时间而不会给应用程序增加太多。

首先:

创建自定义UITabBarController如下:

import UIKit

enum TabbarItemTag: Int {
    case firstViewController = 101
    case secondViewConroller = 102
}

class CustomTabBarController: UITabBarController {
    var firstTabbarItemImageView: UIImageView!
    var secondTabbarItemImageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let firstItemView = tabBar.subviews.first!
        firstTabbarItemImageView = firstItemView.subviews.first as? UIImageView
        firstTabbarItemImageView.contentMode = .center

        let secondItemView = self.tabBar.subviews[1]
        self.secondTabbarItemImageView = secondItemView.subviews.first as? UIImageView
        self.secondTabbarItemImageView.contentMode = .center
    }

    private func animate(_ imageView: UIImageView) {
        UIView.animate(withDuration: 0.1, animations: {
            imageView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
        }) { _ in
            UIView.animate(withDuration: 0.25, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 3.0, options: .curveEaseInOut, animations: {
                imageView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
            }, completion: nil)
        }
    }

    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        guard let tabbarItemTag = TabbarItemTag(rawValue: item.tag) else {
            return
        }

        switch tabbarItemTag {
        case .firstViewController:
            animate(firstTabbarItemImageView)
        case .secondViewConroller:
            animate(secondTabbarItemImageView)
        }
    }
}

其次:

为每个视图控制器设置 tabBarItemtag 值:

第一个ViewController:

import UIKit

class FirstViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        tabBarItem.tag = TabbarItemTag.firstViewController.rawValue
    }
}

第二个ViewController:

import UIKit

class SecondViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        tabBarItem.tag = TabbarItemTag.secondViewConroller.rawValue
    }
}

确保您的故事板(如果您正在使用故事板)已设置好一切,仅此而已!

输出:

您可以查看回购协议:

https://github.com/AhmadFayyas/Animated-TabbarItem/tree/master

为了证明答案。

这对我有用:

class MyCustomTabController: UITabBarController {

    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        guard let barItemView = item.value(forKey: "view") as? UIView else { return }

        let timeInterval: TimeInterval = 0.3
        let propertyAnimator = UIViewPropertyAnimator(duration: timeInterval, dampingRatio: 0.5) {
            barItemView.transform = CGAffineTransform.identity.scaledBy(x: 0.9, y: 0.9)
        }
        propertyAnimator.addAnimations({ barItemView.transform = .identity }, delayFactor: CGFloat(timeInterval))
        propertyAnimator.startAnimation()
    }

}