如何为选项卡栏添加动画效果的项目

5
在我的Swift应用程序中,我有一个处理UITabBar的类。
class CustomTabBar: UITabBar {
    override func awakeFromNib() {
        super.awakeFromNib()
    }
}

当用户点击它们时,我该如何为这些项目添加动画效果? 我指的是 CGAffine(scaleX: 1.1, y: 1.1)。 那么我该如何为选项卡栏中的项目添加动画效果?


请查看 https://github.com/eggswift/ESTabBarController 这个应该会有所帮助。 - Sandeep Bhandari
4个回答

10

首先:

按照以下步骤创建自定义的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值:

第一个视图控制器:

import UIKit

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

第二个视图控制器:

import UIKit

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

确保您的故事板(如果使用)已经设置好,这基本上就是全部内容!

输出:

enter image description here

您可以检查该仓库:

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

用于演示答案。


非常感谢!你的帮助很重要。享受吧。 - Jack K.
1
好的,我明白了,但是我还有另一个问题:didSelect函数不起作用,总是返回所选项目为0。 - Jack K.
1
对于Swift 4:我不得不手动将“tag 101”等添加到Storyboard中的每个tabbaritem,否则它就无法正常工作。 - Wladislaw
谢谢,它对我来说很好用,就像截图中所期望的那样。我给你点赞。 - Dilip Tiwari
我通过在Storyboard中设置每个TabBarItem的标签值来解决了这个问题。 - Dilip Tiwari
显示剩余3条评论

7
这个对我有用:
这个小技巧解决了我的问题。
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()
    }

}

5
由于UITabBarItem不是UIView的子类,而是NSObject的子类,因此没有直接的方法来在选中时对其进行动画处理。
要么挖掘属于该项目的UIView并对其进行动画处理,要么创建一个自定义的标签栏。 这里提供了一些挖掘UIView的想法。以及这里的例子可以了解如何在点击项时触发事件。但是请注意这种方式:
  • Apple有可能更改UITabBar的实现,从而导致问题。
  • 你可能会干扰iOS的动画效果并产生奇怪的影响。
顺便说一句,没有必要子类化UITabBar。只需实现UITabBarDelegate即可。
我实际上建议您坚持使用标准的UITabBar行为和外观选项,并在以后或根本不考虑此事。像这样的东西可能会浪费您的时间,而对应用程序的贡献却很小。

请问你能给我提供一个教程的链接吗? - Jack K.
@JackK。教程通常会讨论公共的iOS功能。所以,我不指望会有一份教程。但是,我在我的编辑中添加的链接应该可以帮助你入门。 - meaning-matters

0
这是一个更优化的解决方案,适用于任意数量的控制器。 请查看代码中的注释以更好地理解逻辑。
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)
    }
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接