美文网首页IOS收藏iOS 动画IOS三人行
TabBarItem添加动画的一种思路

TabBarItem添加动画的一种思路

作者: Calabash_Boy | 来源:发表于2016-07-10 21:27 被阅读3876次

    父老乡亲们,我葫芦娃又回来了~
    今天我们来侃一侃tabBarItem中动画的另一种实现方式;

    前几日学习项目,需要给tabBarItem添加一个类似弹簧效果的动画,原作者的思路是自定义了几个View填充了tabBar,给这些View设置了手势监听来实现动画效果,代码非常繁琐,如果只是简单的让tabBarItem实现需求的动画,我尝试着有没有更简单的方法来做;原项目的效果如下:

    原版动画.gif

    动画的实现,本质来讲就是拿到需要实现动画的UIView,然后把需求动画添加到它的layer上就可以了;
    我们现在的目的就是拿到TabBar上对应的控件,把对应的动画添加上去;这样就可以既使用系统的tabBar原有的功能,又添加了动画;
    假定我现在的需求是只给tabBarItem中的image添加一个弹簧效果;

    • 自定义tabBar
    • 在自定义的tabBar中拿到点击控件,添加点击的监听事件
    • 在监听事件中把动画添加到动画控件的layer上

    (1) 由于tabBartabBarController的只读属性,因此我们用KVC来设置

    - (void)viewDidLoad {   
        [super viewDidLoad];
         //使用KVC来进行设置
        FGTabBar *myTabBar = [[FGTabBaralloc] init];
        [selfsetValue:myTabBar forKey:@"tabBar"]; 
    }
    

    (2) 在自定义的tabBar中,尝试从tabBar的子控件中下手;

    - (void)layoutSubviews
    {
        [super layoutSubviews];
        NSLog(@"%@",self.subviews);
    }
    

    打印结果如下:

     "<_UITabBarBackgroundView: 0x7fddb21236e0; frame = (0 0; 375 49); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fddb21297d0>>",   
     "<UITabBarButton: 0x7fddb23bb500; frame = (2 1; 90 48); opaque = NO; layer = <CALayer: 0x7fddb2130880>>",   
     "<UITabBarButton: 0x7fddb217e1a0; frame = (96 1; 90 48); opaque = NO; layer = <CALayer: 0x7fddb217eec0>>",  
     "<UITabBarButton: 0x7fddb2184700; frame = (190 1; 89 48); opaque = NO; layer = <CALayer: 0x7fddb2184e20>>",  
     "<UITabBarButton: 0x7fddb21893c0; frame = (283 1; 90 48); opaque = NO; layer = <CALayer: 0x7fddb2189b60>>",
     "<UIImageView: 0x7fddb217ea70; frame = (0 -0.5; 375 0.5); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fddb219fa40>>"
    

    中间的四个子控件就是tabBarItem中对应的每个按钮(到这里就可以类比UIButton的思想来继续了),它有没有可能也是继承自UIControl的一种按钮类型?
    layoutSubviews中添加下面的代码:

     for (UIView *tabBarButton in self.subviews) {
         if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) { // 之所以这么写是因为UITabBarButton是苹果私有API
             NSLog(@"%@",tabBarButton.superclass);
           }
      }
    

    打印出的结果不出所料正是UIControl,那么就可以添加addTarget的监听方法;

    (3) 由于需求只是让tabBarButton上的图片进行动画,因此我们通过打印tabBarButton的子控件,可以找到其中展示图片的imageView,把动画添加到这个imageView的layer上就可以了;打印结果如下:

    "<UITabBarSwappableImageView: 0x7fd7ebc52760; frame = (32 5.5; 25 25); opaque = NO; userInteractionEnabled = NO; tintColor = UIDeviceWhiteColorSpace 0.572549 1; layer = <CALayer: 0x7fd7ebc52940>>",
    "<UITabBarButtonLabel: 0x7fd7ebc4f360; frame = (29.5 35; 30 12); text = '\U8d2d\U7269\U8f66'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd7ebc4e090>>"
    

    在监听的方法中,通过与第(2)步类似的步骤,拿到这个ImageView,添加动画就可以了;当然也可以给label添加动画,也可以给整个tabBarButton添加动画;

    完整的代码如下:

    - (void)layoutSubviews{
        [super layoutSubviews]; 
        for (UIControl *tabBarButton in self.subviews) { 
            if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
                [tabBarButton addTarget:selfaction:@selector(tabBarButtonClick:) forControlEvents:UIControlEventTouchUpInside];
            }
        } 
    }
    
    - (void)tabBarButtonClick:(UIControl *)tabBarButton
    { 
        for (UIView *imageView in tabBarButton.subviews) { 
            if ([imageView isKindOfClass:NSClassFromString(@"UITabBarSwappableImageView")]) {
                //需要实现的帧动画,这里根据需求自定义
                CAKeyframeAnimation *animation = [CAKeyframeAnimationanimation];         
                animation.keyPath = @"transform.scale";   
                animation.values = @[@1.0,@1.3,@0.9,@1.15,@0.95,@1.02,@1.0];   
                animation.duration = 1;
                animation.calculationMode = kCAAnimationCubic;
                //把动画添加上去就OK了
                [imageView.layeraddAnimation:animation forKey:nil];  
          }
       }
    }
    

    最后实现的效果如下:


    测试动画.gif

    总结

    因此,如果以后只是单纯的实现tabBarItem上的动画,不需要对tabBar进行大刀阔斧的改动,也可以尝试用这种方法来做;
    今天就先侃到这里了,小弟只是抛砖引玉,大家有建议的话可以留言给我,共同玩耍于iOS乐园;
    散了散了,回家收衣服了~

    相关文章

      网友评论

      • 九林:- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
        {
        viewController.tabBarItem.qmui_imageView.transform = CGAffineTransformMakeScale(0.6,0.6);
        // 弹簧动画,参数分别为:时长,延时,弹性(越小弹性越大),初始速度
        [UIView animateWithDuration: 0.7 delay:0 usingSpringWithDamping:0.3 initialSpringVelocity:0.3 options:0 animations:^{
        // 放大
        viewController.tabBarItem.qmui_imageView.transform = CGAffineTransformMakeScale(1,1);
        } completion:nil];

        }

        还有种方法,设置UITabBarControllerDelegate 也可以
        SDBridge:@九林 O(∩_∩)O谢谢
        九林:@Coder_Hou 你可以看我简书,里面有介绍
        SDBridge:qmui_imageView 这个变量 从哪里来的?
      • 心语风尚:demo呢
      • Rudy_1:你这方法有个bug,程序运行后第一次点击UITabBarItem没有动画效果
      • 会武的锄头:PL,必须点个赞
      • seasonZhu:非常不错的思路,通过博主的思路,我在swift下面也实现了一样的功能.
        animation.values = @[@1.0,@1.3,@0.9,@1.15,@0.95,@1.02,@1.0];这里面值哪位大大帮我解释一下,感谢
        Calabash_Boy:@叆叇云逝 这是CAKeyframeAnimation关键帧动画的知识;
        这个数组表示的是属性值animation.keyPath(Demo中使用的是scale,就是transform的缩放比例)在动画过程中的关键帧,每一个元素都是一个缩放比例,这几个关键帧实现了弹簧的效果.
      • qazws:wonderful
      • Fe_Zn:可以可以,效果看上去挺好的,点赞
        Calabash_Boy:@JsonChan :grin:
      • 751fc49dcbfd:- (void)layoutSubviews{
        每次都添加不好吧 初始化的完毕的时候 那个button应该就已经存在了。 直接加事件应该可以
        Calabash_Boy:@花菜Christi 干的漂亮! :clap:
        Caiflower:这个问题简单,加个GCD的dispatch_once 搞定,收工 :smiley:
        Calabash_Boy:@1140752635 好想法~~
        我之前也是这么想的,因为我是用alloc init创建的自定义tabBar,然后在initWithFrame的方法中打印tabBar的子控件,发现是空的...
        所有就写在了layoutSubviews,这个方法只会调用两次,也不是很频繁 :stuck_out_tongue_closed_eyes:
      • LinkStart:恩,好的
      • LinkStart:额,,,可能我太笨,居然没效果 :sweat:
        Calabash_Boy:@LinkStart 对了,我这都是用纯代码实现的,你可以给tabBarController只添加一个子控制器试试效果~ :blush:
      • WGGHot:抽时间写个demo看看,楼主想法不错
        Calabash_Boy:@来自天王星的人儿 :wink:

      本文标题:TabBarItem添加动画的一种思路

      本文链接:https://www.haomeiwen.com/subject/tkbdjttx.html