美文网首页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