无意间看到一个彩色TabBar切换的设计图,感觉很不错,有空就把他实现了。

环境信息

Mac OS X 10.10.4

Xcode 6.4

iOS 8.4

效果图:

效果图

源码下载地址:

https://github.com/saitjr/STColorfulTabBar.git

正文

一、实现分析

看到这个彩色切换效果的时候,我第一个反应就是在TabBar上有一个彩色的View,然后每个色块的显示都是通过mask来显示的。最终,我的具体实现也是根据这个思路来的。

1. 设计思想

为了减少侵入性(耦合),我采取的是继承UITabBar来实现,所以要集成的时候,只需要将系统的TabBar换成我写的TColorfulTabBar就可以了。

2. 视图层级图

视图层级图

二、效果实现

1. 添加彩色视图colorfulView

TColorfulTabBar.m

  1. - (void)setupColorView {
  2. // 初始化彩色视图,并将它加在tabbar上
  3. UIView *colorView = [[UIView alloc] initWithFrame:self.bounds];
  4. [self addSubview:colorView];
  5. self.colorfulView = colorView;
  6. // 彩色视图的五种颜色,这是一个UIColor数组,
  7. NSArray *colors = self.itemColors;
  8. CGFloat itemWidth = self.bounds.size.width / self.itemCount;
  9. for (int i = 0; i < self.itemCount; i ++) {
  10. UIView *view = [[UIView alloc] initWithFrame:CGRectMake(itemWidth * i, 0, itemWidth, self.bounds.size.height)];
  11. view.backgroundColor = colors[i];
  12. [self.colorfulView addSubview:view];
  13. }
  14. }

2. 添加彩色视图的遮罩colorfulMaskView

之所以这里的遮罩使用的是UIView而不是CAShapeLayer或者CALayer,原因如下:

  • 遮罩是矩形,没必要使用路径,所以不用CAShapeLayer
  • 通过设计图可以看到,在位移动画之前,有一个遮罩单向变宽(向左或向右)的效果。如果使用CALayer,那么改变bounds的时候,是双向改变,想要单向就必须加锚点,太麻烦
  • 如果使用UIView,那么向右变宽只需要x不变,width变长就行;向左变宽只需要x-value,width+value就行,要方便的多
  • 最后一点就是在做动画的时候,Layer要用到CABasicAnimation(CABaseAnimation之前写错了,已修正),然而UIView使用UIView的Animation就行

在设置遮罩的时候,将colorfulMaskView的layer设置为colorfulView的mask就可以了。

代码实现如下:

TColorfulTabBar.m

  1. - (void)setupMaskLayer {
  2. // 获取每个item的宽度
  3. CGFloat itemWidth = self.bounds.size.width / self.itemCount;
  4. // 初始化colorMaskView,并将colorMaskView的layer设置成彩色视图的遮罩
  5. UIView *colorMaskView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemWidth, self.bounds.size.height)];
  6. colorMaskView.backgroundColor = [UIColor blackColor];
  7. self.colorfulMaskView = colorMaskView;
  8. self.colorfulView.layer.mask = self.colorfulMaskView.layer;
  9. }

3. 设置代理,获取当前点击的下标

UITabBar并没有获取点击下标的接口,但是UITabBarDelegate有,这个协议默认被UITabBarController遵守。为了降低耦合性,采用UITabBar自己获取下标,所以,需要UITabBar自己实现自己的delegate。

值得注意的是,不能在UITabBar的初始化方法中去设置self.delegate = self,因为即使设置了,也会被UITabBarController覆盖。最终解决方案是当UITabBar加载到父视图上是,在修改delegate为self。

  1. - (void)didMoveToSuperview {
  2. [super didMoveToSuperview];
  3. self.delegate = self;
  4. }

因为每次的移动位置与方向都和上次的下标与这次的下标有关,所以需要使用到属性来记录这两个下标的值。

  1. - (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
  2. NSInteger index = [self.items indexOfObject:item];
  3. self.fromeIndex = self.toIndex;
  4. self.toIndex = index;
  5. // 拿到下标以后执行动画
  6. [self animation];
  7. }

4. 移动遮罩,显示不同的色块

在做动画的时候,需要考虑到效果的平滑性。整个动画有两个动画组成,一个是宽度放大的动画,一个是缩小到原来大小和位移动画。整个动画是EaseInOut的效果,所以拆开来看,就应该第一个动画EaseIn,第二个动画EaseOut。

一图胜千言:

动画线性图

  1. - (void)animation {
  2. CGFloat itemWidth = self.bounds.size.width / self.itemCount;
  3. // 为了效果看起来更平滑,所以根据两次下标的差值来计算需要放大的距离
  4. CGFloat extraWidth = ABS(self.toIndex - self.fromeIndex) * itemWidth / 4;
  5. // 放大的大小
  6. CGRect scaleFrame = CGRectMake(self.colorfulMaskView.x, 0, itemWidth + extraWidth, self.bounds.size.height);
  7. // 最终大的大小与位置
  8. CGRect toFrame = CGRectMake(self.toIndex * itemWidth, 0, itemWidth, self.bounds.size.height);
  9. // 如果是向左移动,那修改x轴的坐标
  10. if (self.fromeIndex > self.toIndex) {
  11. scaleFrame = CGRectMake(self.colorfulMaskView.x - extraWidth, 0, itemWidth + extraWidth, self.bounds.size.height);
  12. }
  13. // 两个动画加起来是一个EaseInOut的效果,所以第一个动画就应该是EaseIn,第二个动画是EaseOut
  14. // 先进行放大
  15. [UIView animateWithDuration:ANIMATION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  16. self.colorfulMaskView.frame = scaleFrame;
  17. } completion:^(BOOL finished) {
  18. // 再进行缩小和位移
  19. [UIView animateWithDuration:ANIMATION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
  20. self.colorfulMaskView.frame = toFrame;
  21. } completion:NULL];
  22. }];
  23. }

【iOS】彩色TabBar切换动画实现的更多相关文章

  1. IOS自定义场景切换动画。

    IOS中我们可以通过Storyborad以及segue来实现我们自己的场景切换动画,新建项目使用Single View Application模板并取名为MyCustomSegue. 使用storyb ...

  2. iOS 界面翻转切换动画

    [UIView  beginAnimations:nil context:NULL]; [UIView setAnimationCurve:UIViewAnimationCurveLinear]; [ ...

  3. Android的Activity切换动画特效库SwitchLayout,视图切换动画库,媲美IOS

    由于看了IOS上面很多开发者开发的APP的视图界面切换动画体验非常好,这些都是IOS自带的,但是Android的Activity等视图切换动画并没有提供原生的,所以特此写了一个可以媲美IOS视图切换动 ...

  4. iOS页面切换动画实现方式。

    iOS页面切换动画实现方式. 1.使用UIView animateWithDuration:animations:completion方法 Java代码 [UIView animateWithDura ...

  5. IOS 视图切换动画

    我在网上找到的这个小方法,被我举一反三使用的屡试不爽.比如用在,当视图需要执行某一方法跳转到新的一个UIView上,从底层渐变浮到最上层.就是一个不错的视觉效果或者当需要类似keyboard的效果从底 ...

  6. jQuery Mobile 连接外部连接或切换动画

    jQuery Mobile不同网页之间的跳转问题 jQuery Mobile,一个新的手机终端脚本开发库,从名字可以看出,它是基于jQuery:目前支持很多种手机设备,包括IOS/Android/Bl ...

  7. IOS开发系列 --- 核心动画

    原始地址:http://www.cnblogs.com/kenshincui/p/3972100.html 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...

  8. ios图层转场动画

    动画类型 CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 UINavigationController就是通过CA ...

  9. Swift:超炫的View Controller切换动画

    匿名社交应用Secret的开发者开发了一款叫做Ping的应用,用户可以他们感兴趣的话题的推送. Ping有一个很炫的东西,就是主界面和之间切换的动画做的非常的好.每次看到一个非常炫的动画,都不由得会想 ...

随机推荐

  1. .net using使用小结

    在.net中using使用方法有3种,分别是using指令.using定义使用范围.using别名. using指令,即引用命名空间. using System; using System.Colle ...

  2. Elasticsearch增删改查 之 —— mget多文档查询

    之前说过了针对单一文档的增删改查,基本也算是达到了一个基本数据库的功能.本篇主要描述的是多文档的查询,通过这个查询语法,可以根据多个文档的查询条件,返回多个文档集合. 更多内容可以参考我整理的ELK文 ...

  3. CSS魔法堂:你一定误解过的Normal flow

    前言  刚接触CSS时经常听到看到一个词"文档流",那到底什么是"文档流"呢?然后会看到"绝对定位和浮动定位能脱离文档流",从这句可以看到文 ...

  4. C#--声明类

  5. log4net的配置详解

    log4net是一款优秀的第三方日志框架,可以很容易的加载到开发项目中(引用log4net的dll,再配置些基本参数即可),帮助程序员把日志信息输出到各种不同的目标,常见的有文本.数据库.window ...

  6. 获取MS SQL TABLE列名列表

    在MS SQL Server中,想获取表的所有列名,可以使用下面SQL语句: SELECT [COLUMN_NAME] FROM [INFORMATION_SCHEMA].[Columns] WHER ...

  7. 基于Winform的.cs文件命名空间排序及注释批量处理工具

    公司里每个程序员在命名空间的排序和注释上都有很多的不同. 杂乱的命名空间: using System; using System.Collections.Generic; using Autodesk ...

  8. 使用NVelocity生成内容的几种方式

    使用NVelocity也有几个年头了,主要是在我的代码生成工具Database2Sharp上使用来生成相关代码的,不过NVelocity是一个非常不错的模板引擎,可以用来生成文件.页面等相关处理,非常 ...

  9. Entity Framework 的简单介绍与实例

    1.下载与引用 a) 首先需要下载一个oracle clinent 12c 发行版(我这边下载的是发行版)并进行安装,下载内容如下图 B) 创建一个项目,通过Nuget引用  添加ODP.NET    ...

  10. 字符串-Alphabet

    在一些应用当中,会对字符串的字母表进行限制,在这些应用中,往往会用到如下的示例所涉及到的几点知识: public static void main(String[] args){ String[] a ...