【问题标题】:UITabBarItem Icon AnimationUITabBarItem 图标动画
【发布时间】:2011-04-01 00:10:58
【问题描述】:

iPhone 版 Skype 应用程序使用动画 TabBar 图标。例如,在登录过程中,最右侧的选项卡图标显示循环箭头。在调用“通话”标签时,图标会轻轻闪烁,这显然是通过动画完成的。

我想知道如何为标签栏项目的图标设置动画。

在我的特殊情况下,当用户按下“收藏夹”按钮时,它会跳转到“收藏夹”标签栏项目。我已经实现了跳跃动画,但是我希望相应的标签栏图标在动画结束时闪烁,给它带来完整的感觉。

关于我应该研究的方向有什么建议吗?

提前致谢。

【问题讨论】:

标签: iphone animation uitabbaritem


【解决方案1】:

我很惊讶解决方案如此简单!

将方法添加到您的 Application Delegate 类 .m 文件(或管理您的 UITabBar 的任何其他类),其中包含以下例程:

  1. 创建一个将用于动画的 UIImageView。
  2. 使用addSubview: 方法将其添加到您的TabBar 视图中。
  3. 将其框架缩小到 UITabBarItem 的大小(使用 UITabBar 框架大小和标签栏项目的数量来计算框架大小)。
  4. 调整 imageView 的 frame.origin.x 值,将 Image 放在要设置动画的选项卡 bat 项目的正上方。
  5. 将您想要的动画添加到 imageView(您可以使用不透明度进行播放,交换多个图像 - 任何您想要的)。

很简单,你不这么认为吗?

您可以在 UIApplicationDelegate 实例上调用此方法,以便为标签栏项目设置动画。

同样重要的是要注意,您可以通过 imageView 点按来选择标签栏项目,就好像标签栏上没有图像一样。如果你知道的话,你可以在这里做很多有趣的结论......

【讨论】:

    【解决方案2】:

    我找到了解决这个问题的更好方法。添加自定义图像视图不是更好的方法,因为在 iOS 10.0 及更高版本中,更改方向后,图标框架和文本位置发生了变化。您只需要设置 UITabBarController 的类并输入以下代码。

    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    
        let index = self.tabBar.items?.index(of: item)
        let subView = tabBar.subviews[index!+1].subviews.first as! UIImageView
        self.performSpringAnimation(imgView: subView)
    }
    
    //func to perform spring animation on imageview
    func performSpringAnimation(imgView: UIImageView) {
    
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
    
            imgView.transform = CGAffineTransform.init(scaleX: 1.4, y: 1.4)
    
            //reducing the size
            UIView.animate(withDuration: 0.5, delay: 0.2, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
                imgView.transform = CGAffineTransform.init(scaleX: 1, y: 1)
            }) { (flag) in
            }
        }) { (flag) in
    
        }
    }  
    

    【讨论】:

      【解决方案3】:

      请记住,UITabBar 中子视图的顺序可能是无序的,因此使用索引从中访问正确的项目可能无法像Naresh answer 建议的那样正常工作。看看这个帖子UITabBar subviews change order

      我找到的解决方案是先过滤和排序视图,然后使用 tabBarItem 的正确索引访问它。

      func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
      
          let orderedTabBarItemViews: [UIView] = {
              let interactionViews = tabBar.subviews.filter({ $0 is UIControl })
              return interactionViews.sorted(by: { $0.frame.minX < $1.frame.minX })
          }()
      
          guard
              let index = tabBar.items?.firstIndex(of: item),
              let subview = orderedTabBarItemViews[index].subviews.first
          else {
              return
          }
      
          performSpringAnimation(for: subview)
      }
      
      func performSpringAnimation(for view: UIView) {
          UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
              view.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
              UIView.animate(withDuration: 0.5, delay: 0.2, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
                  view.transform = CGAffineTransform(scaleX: 1, y: 1)
              }, completion: nil)
          }, completion: nil)
      }
      

      【讨论】:

      • 它不工作。我已将其添加到标签栏控制器中。代码也在运行,但没有发生任何操作。
      • 同样,我也将这个添加到委托函数中,但没有发生任何事情
      • 尝试创建自己的UITabBarController 子类,它也符合UITabBarControllerDelegate,并将其委托设置为self。我刚刚在 iOS 14.5 上再次尝试过,它仍然有效。
      【解决方案4】:
      【解决方案5】:

      您可以通过获取其视图为标签栏图标设置动画,然后为 UIView 执行任何您喜欢的动画。下面是一个简单的比例变换示例,加油!

      func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem){
              var tabBarView: [UIView] = []
      
              for i in tabBar.subviews {
                  if i.isKind(of: NSClassFromString("UITabBarButton")! ) {
                      tabBarView.append(i)
                  }
              }
      
              if !tabBarView.isEmpty {
                  UIView.animate(withDuration: 0.15, animations: {
                      tabBarView[item.tag].transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
                  }, completion: { _ in
                      UIView.animate(withDuration: 0.15) {
                          tabBarView[item.tag].transform = CGAffineTransform.identity
                      }
                  })
              }
          }
      

      ps:请按顺序为每个UITabBarItem分配标签

      【讨论】:

        【解决方案6】:

        subviews 中的UIImageView 的索引不能保证为拳头。

        UIImageView 的索引在相关子视图中不保证为第一。

        所以最好通过类类型来访问它,并检查索引是否越界。

        override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
            guard let idx = tabBar.items?.firstIndex(of: item),
                tabBar.subviews.count > idx + 1,
                let imageView = tabBar.subviews[idx + 1].subviews.compactMap({ $0 as? UIImageView }).first else {
                return
            }
            
            imageView.layer.add(bounceAnimation, forKey: nil)
        }
        

        这是使用CAKeyframeAnimation 的基本弹跳动画示例:

        private var bounceAnimation: CAKeyframeAnimation = {
            let bounceAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
            bounceAnimation.values = [1.0, 1.3, 0.9, 1.0]
            bounceAnimation.duration = TimeInterval(0.3)
            bounceAnimation.calculationMode = CAAnimationCalculationMode.cubic
            return bounceAnimation
        }()
        

        【讨论】:

        • 你如何在stackoverflow上的问题上发布这样的gif?
        【解决方案7】:

        在目标 c 中为标签栏项目设置动画的简单方法

        在您的标签栏控制器类中

            - (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
            {
                UIVisualEffectView *viv = tabBar.subviews[item.tag].subviews.firstObject;
                UIImageView *img = viv.contentView.subviews.firstObject;
               // If UIImageView not get use this code
               // UIImageView *img  = tabBar.subviews[item.tag].subviews.lastObject;
        
        
                [self shakeAnimation:img];
              //[self bounceAnimation:img];
        
            }
        
        
        
        - (void)shakeAnimation:(UIImageView *)img
        {
            CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
            [animation setDuration:0.05];
            [animation setRepeatCount:2];
            [animation setAutoreverses:YES];
            [animation setFromValue:[NSValue valueWithCGPoint: CGPointMake([img center].x - 10.0f, [img center].y)]];
            [animation setToValue:[NSValue valueWithCGPoint: CGPointMake([img center].x + 10.0f, [img center].y)]];
            [[img layer] addAnimation:animation forKey:@"position"];
        }
        
        
        - (void)bounceAnimation:(UIImageView *)img
        {
            img.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001);
        
            [UIView animateWithDuration:0.3/1.5 animations:^{
                img.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
            } completion:^(BOOL finished) {
                [UIView animateWithDuration:0.3/2 animations:^{
                    img.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9);
                } completion:^(BOOL finished) {
                    [UIView animateWithDuration:0.3/2 animations:^{
                        img.transform = CGAffineTransformIdentity;
                    }];
                }];
            }];
        }
        

        【讨论】:

          【解决方案8】:

          我还没有这样做,但我只是尝试构建一个 CAAnimation,例如使用 CABasicAnimation 并将其添加到要设置动画的 UITabBarItem 中。

          有关如何设置 CABasicAnimation 的详细信息,请参阅核心动画编程指南: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/AnimatingLayers.html#//apple_ref/doc/uid/TP40006085-SW1

          【讨论】:

          • 不,我相信这不会起作用,因为 UITabBarItem 不是一种视图 - 它源自 NSObjest(基本类)和 UIBarItem(那里也没什么有趣的)。似乎没有图层甚至框架可以玩。但我已经设法通过进入“后门”解决了这个问题。谢谢你的想法
          猜你喜欢
          • 1970-01-01
          • 2021-05-06
          • 2013-04-23
          • 2012-05-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-28
          • 1970-01-01
          相关资源
          最近更新 更多