程序猿阵线联盟-汇总各类技术干货程序员

iOS--如何写一个微博导航栏动画(CoreGraphics)

2018-07-09  本文已影响24人  酷酷的程序员呀

前言

昨天刚做完项目的新版本、除了尝试一些新的架构之外、功能方面并没什么特别的地方。

但是顺手搞了一些还算好玩的东西、其一就是这个导航栏的动画。

感觉还算简单易懂、分享一下(其实更多是最近攒了好多封面、不贴出来憋得人难受)。

导航栏动画.gif

思路

先介绍CA的两个方法:

基于原始状态的位移

CG_EXTERNCGAffineTransformCGAffineTransformMakeTranslation(CGFloattx,CGFloatty)CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

基于原始状态的形变

CG_EXTERNCGAffineTransformCGAffineTransformScale(CGAffineTransformt,CGFloatsx,CGFloatsy)CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

知道了这两个方法、剩下就是如何使用形变和位移以达到想要的效果了。

这里、需要分两部分来看、一部分是位移、一部分是形变

而且、如果将一整个动画以及翻页动作看成1。那么位移和形变又需要分成两部分来看:0到0.5以及0.5到1。

其实一点都不难、画个图看一眼。连一元方程都不算、完全是小学算术题~甚至连奥数都算不上。

0到0.5区间内

先看形变

在0.5时、我们需要将线条长度从left_width形变成max_width

形变-0到0.5

再看位移

与此同时如果想让线条在左侧看起来并没有移动、就需要将线条的x轴一点点向右移动。这个移动的值呢?

由于形变是双向的、右侧和左侧都会变长。那么对于左侧最终将是中间时最终形变差值的一半。

具体到数值:

最左侧到中心点时x轴的位移 = 最左侧到中心点时形变的差值/2 = (max_width - left_width)/2

0.5到1区间内

依旧先看形变

和之前的形变相同

形变-0.5到1

然后来看位移

同理、如果我的长度减少了X、那么我如果想保证看起来右侧位置不会改变、考虑到形变是左右同时发生、就需要向右移动X/2。

具体到数值:

中心点到最右侧时x轴的位移 = 中心点到最右时形变的差值/2 = (max_width - right_width)/2

具体函数

以我项目里两个按钮(self.titleBtn1/self.titleBtn2)为例

if(0<= offsetRate && offsetRate <=0.5) {/*

        * 左侧与中间相互移动

        *///x轴位移 :: 中间时位移 * 偏移比例系数CGFloattranslationOfX = _translationofX_center * offsetRate *2;self.line.transform =CGAffineTransformMakeTranslation(translationOfX,0);//x轴形变 :: 1 + (最大时相对形变) * 偏移比例系数CGFloatflagScale =1+ (_flagScale_center -1) * (offsetRate *2);self.line.transform =CGAffineTransformScale(self.line.transform, flagScale,1);            }elseif(0.5< offsetRate && offsetRate <=1) {/*

        * 中间与右侧相互移动

        *///x轴位移 :: 中间时位移 + 最终位移 * 偏移比例系数CGFloattranslationOfX = _translationofX_center + _translationofX_right * (offsetRate -0.5) *2;self.line.transform =CGAffineTransformMakeTranslation(translationOfX,0);//x轴形变 :: 最大时形变 - (最大形变 - 最终形变) * 偏移比例系数CGFloatflagScale = _flagScale_center - (_flagScale_center - _btn2Width/_btn1Width) * (offsetRate -0.5) *2;self.line.transform =CGAffineTransformScale(self.line.transform, flagScale,1);    }

其中的某些参数的意义以及取值:

{//整体最大宽度CGFloat_maxWidth;//位于左侧时宽度CGFloat_btn1Width;//位于右侧时宽度CGFloat_btn2Width;//从左侧移到中心时x轴位移CGFloat_translationofX_center;//从中心移到右侧时x轴位移//所以总位移就是_translationofX_center+_translationofX_rightCGFloat_translationofX_right;//位于中心时形变CGFloat_flagScale_center;}{    _btn1Width =self.titleBtn1.width;    _btn2Width =self.titleBtn2.width;    _maxWidth =self.titleBtn2.right -self.titleBtn1.left;    _translationofX_center = (_maxWidth - _btn1Width)/2;    _translationofX_right = (_maxWidth - _btn2Width)/2;    _flagScale_center = _maxWidth/_btn1Width;self.line.frame =CGRectMake(self.titleBtn1.left,self.height,self.titleBtn1.width,1);}

将屏幕滑动的偏移量传递进来

#pragma mark UIScrollViewDelegate- (void)scrollViewDidScroll:(UIScrollView*)scrollView {CGFloatoffsetX = scrollView.contentOffset.x;CGFloatoffsetRate = offsetX/BSScreen_Width;//将偏移率传递给navView[self.navView configLingWithOffsetRate:offsetRate];}

Demo

上面的例子的代码其实都已经列出来了、没什么再单独传Demo的必要。

但是毕竟开了个帖子、连个Demo都没有不好看。于是上午干脆封装了一个小工具出来。

但是只封装了移动的动画、并没封装按钮变色等等一系列功能。

KTNavDemo.gif

用起来也挺简单的、只要将按钮的数组、下方横线交付、在屏幕滑动的时候把偏移量传递进去、就能自动工作了。宽度啊什么都会自己算:

@interfaceKTNavScrollTool : NSObject/** 初始化@paramtitleArr 按钮数组@paramline 需要移动的横线@return实例对象 */- (instancetype)initWithTitleArr:(NSArray  *)titleArr line:(UIView *)line;/** 移动的函数@paramoffsetRate scrollview滚动式的偏移量的比例 */- (void)configLingWithOffsetRate:(CGFloat)offsetRate;@end

GitHub有兴趣可以自取

         欢迎入群交流 内有面试技巧文件   欢迎加入786735421 一起学习ios  为成为大神之路加油!!

                     文章来源网络   侵权请联系小编   删除~

上一篇下一篇

猜你喜欢

热点阅读