如何在UITabBar中检测UIControlEvents.touchDown事件以实现标签按下动画?
如何在UITabBar标签被按下时响应touchDown事件并启动动画
要实现UITabBarItem在用户按下(而非选中后)就触发动画,我们需要绕过UITabBarDelegate的局限,直接给底层的标签按钮添加事件监听。下面是具体的实现方案:
核心思路
UITabBar的每个标签对应的是私有类UITabBarButton(属于UIControl子类),我们可以遍历UITabBar的子视图找到这些按钮,然后为它们添加UIControlEvents.touchDown事件的处理器,从而在用户按下标签的瞬间触发动画。
步骤1:为UITabBarButton添加touchDown监听
在你的ViewController(比如TabBarController或者嵌入TabBar的ViewController)中,添加以下代码来遍历并绑定事件:
override func viewDidLoad() { super.viewDidLoad() setupTabBarTouchDownListeners() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 每次视图出现时重新绑定,避免标签动态变化后监听失效 setupTabBarTouchDownListeners() } private func setupTabBarTouchDownListeners() { guard let tabBar = self.tabBar else { return } // 先移除旧的监听,避免重复绑定 for view in tabBar.subviews { if view.isKind(of: NSClassFromString("UITabBarButton")!) { view.removeTarget(self, action: #selector(tabBarButtonTouchedDown(_:)), for: .touchDown) view.addTarget(self, action: #selector(tabBarButtonTouchedDown(_:)), for: .touchDown) } } }
步骤2:实现touchDown事件的处理逻辑
编写事件处理器,找到对应的UITabBarItem并执行动画:
@objc private func tabBarButtonTouchedDown(_ sender: UIControl) { guard let tabBar = self.tabBar, let buttonIndex = tabBar.subviews.firstIndex(of: sender), buttonIndex < tabBar.items?.count ?? 0 else { return } let selectedItem = tabBar.items![buttonIndex] animateTabBarItem(selectedItem) }
步骤3:编写UITabBarItem的动画函数
这里以一个简单的缩放动画为例,你可以根据需求自定义动画效果:
private func animateTabBarItem(_ item: UITabBarItem) { // 通过私有key获取UITabBarItem对应的视图(注意:这是访问私有属性,审核时可能有极小风险,但多数场景下可通过) guard let itemView = item.value(forKey: "view") as? UIView else { return } UIView.animate(withDuration: 0.15, animations: { itemView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) }) { _ in UIView.animate(withDuration: 0.15) { itemView.transform = .identity } } }
注意事项
- 私有API风险:我们用到了私有类
UITabBarButton和私有属性view,虽然在大多数情况下App Store审核会通过,但苹果的审核规则可能会变化,若担心风险,也可以通过自定义UITabBar来替代系统的UITabBar,完全控制每个标签的交互事件。 - 动态标签适配:如果你的UITabBarItem是动态添加/移除的,记得在变化后重新调用
setupTabBarTouchDownListeners()来绑定新的按钮监听。 - 避免重复绑定:在
viewWillAppear中重新绑定时,先移除旧的监听,防止同一个按钮被多次绑定事件。
内容的提问来源于stack exchange,提问作者rob
相关产品推荐
相关产品推荐

