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

问题描述 投票:0回答:5

在我的 Swift 应用程序中,我有一个处理

UITabBar
的类。

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

当用户点击项目时,如何为项目设置动画? 我的意思是

CGAffine(scaleX: 1.1, y: 1.1)
那么我如何才能为标签栏的项目设置动画呢?

ios swift uitabbarcontroller
5个回答
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)
        }
    }
}

第二:

设置每个视图控制器的
tag
tabBarItem
值:

第一个视图控制器:

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

确保一切都已通过故事板设置完毕(如果您正在使用故事板),仅此而已!

输出:

您可以检查存储库:

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

用于演示答案。


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
行为和蒙皮选项,然后稍后再解决,或者根本不解决。诸如此类的事情会消耗您的时间,而无需为应用程序添加太多内容。


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

}


0
投票

也可以将动画应用到 UIView 层。这是一个例子

class TabBarController: UITabBarController {
    private var tapAnimation: CAKeyframeAnimation {
        let animation = CAKeyframeAnimation(keyPath: "transform.scale")
        animation.values = [1.0, 0.75, 1.0]
        animation.duration = 0.2
        return animation
    }
    
    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        guard let index = self.tabBar.items?.firstIndex(of: item) else { return }
        let tabView = tabBar.subviews[index + 1]
        tabView.layer.add(tapAnimation, forKey: nil)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.