如何为标签栏的项目设置动画
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)
}
}
}
其次:
为每个视图控制器设置 tabBarItem
的 tag
值:
第一个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()
}
}
在我的 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)
}
}
}
其次:
为每个视图控制器设置tabBarItem
的 tag
值:
第一个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()
}
}