ios 如何动画标签栏的项目

mspsb9vt  于 2023-06-25  发布在  iOS
关注(0)|答案(4)|浏览(114)

在我的Swift应用中,我有一个类来处理UITabBar

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

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

vngu2lb8

vngu2lb81#

首先:

创建自定义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
    }
}

确保一切都已设置与您的故事板(如果您正在使用一个),这是差不多了!

输出:

你可以查看repo:
https://github.com/AhmadFayyas/Animated-TabbarItem/tree/master
来证明答案。

dfty9e19

dfty9e192#

这对我来说是个窍门:

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()
    }

}
f8rj6qna

f8rj6qna3#

因为UITabBarItem不是UIView子类,而是NSObject子类,所以没有直接的方法来在点击项目时设置动画。
你要么要挖掘属于该项目的UIView并将其动画化,要么创建一个自定义标签栏。
Here是挖掘UIView的一些想法。以及here for example如何在项目被点击时触发。但是要非常小心地使用这种方法:

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

顺便说一下,没有必要子类化UITabBar。实现UITabBarDelegate就是你所需要的。
实际上我会建议你坚持使用标准的UITabBar行为和皮肤选项,然后再解决这个问题,或者根本不解决。像这样的事情会浪费你的时间,而不会给应用程序增加太多。

enyaitl3

enyaitl34#

这里是更优化的解决方案与任何数量的控制器。查看代码中的注解以更好地理解逻辑。

class TabBarViewController: UITabBarController, UITabBarControllerDelegate {

// MARK: - UI Properties

private var firstVC = UIViewController()

private var secondVC = UIViewController()

private let thirdVC = UIViewController()
    
private var tabBarImageViews: [UIImageView] = []

public lazy var tabBarHeight =  tabBarController?.tabBar.frame.size.height

// Tag to set tabBar items and images to animate
private let startTagValue = 100

// MARK: - Lifecycle

override func viewDidLoad() {
    super.viewDidLoad()
    self.delegate = self
    setControllers()
    
    // Set images to animate possibility
    let tabBarSubviews = tabBar.subviews
    var imageViewTag = startTagValue
    for subview in tabBarSubviews {
        if let imageView = subview.subviews.first as? UIImageView {
            imageView.contentMode = .center
            imageView.tag = imageViewTag
            imageViewTag += 1
            tabBarImageViews.append(imageView)
        }
    }
}

// MARK: - Methods

private func setControllers() {
    let controllers = [firstVC, secondVC, thirdVC]
    
    viewControllers = controllers.map { UINavigationController(rootViewController: $0)}
    
    // Set tag to each tabBarItem to know what imageView to animate
    var controllerItemTag = startTagValue
    controllers.forEach { controller in
        controller.tabBarItem.tag = controllerItemTag
        controllerItemTag += 1
    }
}

private func animate(_ imageView: UIImageView) {
    UIView.animate(withDuration: 0.1, animations: {
        imageView.transform = CGAffineTransform(scaleX: 1.15, y: 1.15)
    }) { _ 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)
    }
}

// MARK: - Delegate Methods

override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    if let imageToAnimate = tabBarImageViews.first(where: { $0.tag == item.tag }) {
        animate(imageToAnimate)
    }
}

}

相关问题