iOS仿微博导航栏动画(CoreGraphics)的实现方法

前言

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

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

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

导航栏动画.gif

思路

先介绍CA的两个方法:

基于原始状态的位移

CG_EXTERN CGAffineTransform CGAffineTransformMakeTranslation(CGFloat tx,
 CGFloat ty) CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

基于原始状态的形变

CG_EXTERN CGAffineTransform CGAffineTransformScale(CGAffineTransform t,
 CGFloat sx, CGFloat sy) 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

再看位移

与此同时如果想让线条在左侧看起来并没有移动、就需要将线条的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轴位移 :: 中间时位移 * 偏移比例系数
  CGFloat translationOfX = _translationofX_center * offsetRate * 2;
  self.line.transform = CGAffineTransformMakeTranslation(translationOfX, 0);

  //x轴形变 :: 1 + (最大时相对形变) * 偏移比例系数
  CGFloat flagScale = 1 + (_flagScale_center - 1) * (offsetRate * 2);
  self.line.transform = CGAffineTransformScale(self.line.transform, flagScale, 1);

 }else if (0.5 < offsetRate && offsetRate <= 1) {
  /*
   * 中间与右侧相互移动
   */

  //x轴位移 :: 中间时位移 + 最终位移 * 偏移比例系数
  CGFloat translationOfX = _translationofX_center + _translationofX_right * (offsetRate - 0.5) * 2;
  self.line.transform = CGAffineTransformMakeTranslation(translationOfX, 0);

  //x轴形变 :: 最大时形变 - (最大形变 - 最终形变) * 偏移比例系数
  CGFloat flagScale = _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_right
 CGFloat _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 {

 CGFloat offsetX = scrollView.contentOffset.x;
 CGFloat offsetRate = offsetX/BSScreen_Width;

 //将偏移率传递给navView

 [self.navView configLingWithOffsetRate:offsetRate];
}

Demo

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

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

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

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

@interface KTNavScrollTool : NSObject

/**
 初始化

 @param titleArr 按钮数组
 @param line 需要移动的横线
 @return 实例对象
 */
- (instancetype)initWithTitleArr:(NSArray<UIView *> *)titleArr line:(UIView *)line;

/**
 移动的函数

 @param offsetRate scrollview滚动式的偏移量的比例
 */
- (void)configLingWithOffsetRate:(CGFloat)offsetRate;
@end

GitHub有兴趣可以自取  (本地下载)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

时间: 2018-07-03

iOS实现顶部标签式导航栏及下拉分类菜单

本文实例为大家分享了iOS实现顶部标签式导航栏及下拉分类菜单的全部过程,供大家参考,具体内容如下 当内容及分类较多时,往往采用顶部标签式导航栏,例如网易新闻客户端的顶部分类导航,最近刚好有这样的应用场景,参考网络上一些demo,实现了这种导航效果,记录一些要点. 效果图(由于视频转GIF掉帧,滑动和下拉动画显得比较生硬,刚发现quickTime可以直接录制手机视频,推荐一下,很方便) 1.顶部标签式导航栏 (1)实现思路 其实就是在上下两个UIScrollView上做文章,实现联动选择切换的效果

iOS11适配工作及导航栏影藏返回文字的解决方法

前言 本文主要介绍了关于iOS11适配及导航栏影藏返回文字的解决方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 一.iOS11适配工作 这是一篇 WWDC Session 204 "Updating Your App for iOS 11" 的总结,里面的内容涉及到了产品.设计以及开发需要了解的内容. 在 "iPad" 以及 "iPhone 的 Landscape" 下, UITabBarItem 图片和文字并排排列了,并

IOS仿今日头条滑动导航栏

之前在我们平台给大家分享了网易首页导航封装类.网易首页导航封装类优化,今天在前两个的基础上仿下今日头条. 1.网易首页导航封装类中主要解决了上面导航的ScrollView和下面的页面的ScrollView联动的问题,以及上面导航栏的便宜量. 2.网易首页导航封装类优化中主要解决iOS7以上滑动返回功能中UIScreenEdgePanGestureRecognizer与ScrollView的滑动的手势冲突问题. 今天仿今日头条滑动导航和网易首页导航封装类优化相似,这个也是解决手势冲突,UIPanG

iOS实现知乎和途家导航栏渐变的文字动画效果

效果图如下 分析如下: 1.导航栏一开始是隐藏的,随着scrollView滚动而渐变 2.导航栏左右两边的navigationItem是一直显示的 3.导航栏参考了途家app,使用了毛玻璃效果,背景是一张图片 4.下拉放大图片效果 5.title文字动画效果 通过简单分析,系统的导航栏实现以上效果有点困难,直接自定义一个假的导航栏更容易点 分布拆解实现以上效果 一.下拉放大header图片 - (void)viewDidLoad { [super viewDidLoad]; [self.view

iOS如何为导航栏添加播放动画

本文实例为大家分享了iOS为导航栏添加播放动画的具体代码,供大家参考,具体内容如下 FLAudioVisualizerView.h #import <UIKit/UIKit.h> @interface FLAudioVisualizerView : UIView #pragma mark - // 默认UIEdgeInsetsZero @property (nonatomic, assign) UIEdgeInsets contentInsets; // 默认为4 @property (non

iOS应用开发中导航栏按钮UIBarButtonItem的添加教程

1.UINavigationController导航控制器如何使用 UINavigationController可以翻译为导航控制器,在iOS里经常用到. 我们看看它的如何使用: 下面的图显示了导航控制器的流程.最左侧是根视图,当用户点击其中的General项时 ,General视图会滑入屏幕:当用户继续点击Auto-Lock项时,Auto-Lock视图将滑入屏幕.相应地,在对象管理上,导航控制器使用了导航堆栈.根视图控制器在堆栈最底层,接下来入栈的是General视图控制器和Auto-Lock

iOS App开发中导航栏的创建及基本属性设置教程

文件目录如下:基本导航顺序: root -> First -> Second -> Third.其中,FirstViewController作为 navigation堆栈的rootview 1.创建navigation 如果是想直接把navigation导航作为项目一开始的跟视图,把RootViewController.h文件里的nav属性放到AppDelegate.h里即可,再把RootViewController.m文件里的action的代码复制到 AppDelegate.m里的di

两种iOS隐藏导航栏的正确方法

简介 在项目中经常碰到首页顶部是无限轮播,需要靠最上面显示.有的设置导航栏为透明等一系列的方法,这个可以借助第三方.或者干脆简单粗暴的直接隐藏掉导航栏.可是push到下一个页面的时候是需要导航栏的,如何做了,这里给出两种方法. 第一种做法 -注意这里一定要用动画的方式隐藏导航栏,这样在使用滑动返回手势的时候效果最好,和上面动图一致.这样做有一个缺点就是在切换tabBar的时候有一个导航栏向上消失的动画. - (void)viewWillAppear:(BOOL)animated { [super

详解iOS11关于导航栏问题

前言 iOS11导航栏除了新加入了largeTitles和searchController两个新特性,可能是加入largeTitles的原因其结构较iOS 10发生了些变化. iOS11之前导航栏的navigationBarButton则直接添加在navigationBar上面 在iOS11之后,苹果添加了新的类来管理,可以看到titleView直接加在_UINavigationBarContentView上,UIBarButtonItem则添加在_UIButtonBarStackView上面,

iOS实现导航栏透明示例代码

在最近一个项目中碰到这样一个场景,在被push进来的一个页面设置导航栏透明,且要求控制对tableview组的头视图进行悬停显示,nav随着tableview偏移量改变透明度,当然这样的需求确实不是什么难事,但是如果当前页面继续push一个不需要此类效果的页面,当在返回当前页面的时候就会出现一个坑,nav的展示很突兀,下面是直接上解决方法...ps:假设A页面为需要设置透明,B页面被Apush且不需要设置透明 首先在需要设置导航栏透明的页面的viewDidload中写上 self.title =

element-ui 实现响应式导航栏的示例代码

开始之前 按照计划,前端使用Vue.js+Element UI,但在设计导航栏时,发现element没有提供传统意义上的页面顶部导航栏组件,只有一个可以用在很多需要选择tab场景的导航菜单,便决定在其基础上改造,由于我认为实现移动端良好的体验是必须的,所以便萌生了给其增加响应式功能的想法. 需求分析与拆解 假设我们的导航栏有logo和四个el-menu-item. 给window绑定监听事件,当宽度小于a时,四个链接全部放入右侧el-submenu的子菜单: 当宽度大于a时,右侧el-subme

iOS 封装导航栏及返回,获取控件所在控制器的实例

当一个项目发现每个返回的按钮都是一样的,并且标题的字体也不是系统的字体,如果每个页面都去设置返回按钮,重新设置标题字体,这样代码看着繁杂,而且会浪费很多时间,这时候就有必要封装一下了... 首先返回按钮,需要在当前页面pop 到上一个页面的话,有两种方式:一 写一个点击代理,在用到的页面实现它,二 就是获取button所在的当前控制器,然后pop出去. 但是第一个方法,还需要到用到的页面去实现代理,也比较麻烦,那就来说第二种 首先获取当前控制器的方法: UINavigationControlle

iOS 设置导航条透明效果的实例代码

APP中很多界面都是这样的.从有不透明到透明,透明到不透明 以下代码即可实现该功能 //设置导航栏透明 func setNavigationIsTranslucent(isTranslucent:Bool) { if isTranslucent == true { self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) self.navigationController?.navi

微信小程序MUI导航栏透明渐变功能示例(通过改变rgba的a值实现)

本文实例讲述了微信小程序MUI导航栏透明渐变功能.分享给大家供大家参考,具体如下: 导航栏透明渐变效果 实现原理 1. 给page-group设置的背景颜色采用rgba; 2. 通过改变rgba其中a的值来实现透明渐变. WXML <view style="height:100%;position:fixed;width:100%;"> <scroll-view scroll-y="false" bindscroll="scroll&qu

微信小程序MUI导航栏透明渐变功能示例(通过改变opacity实现)

本文实例讲述了微信小程序MUI导航栏透明渐变功能.分享给大家供大家参考,具体如下: 导航栏透明渐变效果 实现原理 1. 利用position:absolute在导航下定位一个view作为背景渐变使用; 2. 通过改变改view的opacity来实现透明渐变. WXML <!--pages/scroll/scroll.wxml--> <view style="height:100%;position:fixed;width:100%;"> <scroll-v

iOS中导航栏的基本使用汇总

一.设置导航栏样式 设置导航栏的样式可分为全局设置与局部设置: 1.全局设置 全局设置一般的都是在AppDelegate中设置,这样整个app都会生效,相关的代码与效果图如下: //1.设置导航栏背景颜色 [[UINavigationBar appearance] setBarTintColor:[UIColor orangeColor]]; //2.设置导航栏背景图片 [[UINavigationBar appearance] setBackgroundImage:[UIImage image

IOS 改变导航栏返回按钮的标题实例详解

IOS 改变导航栏返回按钮的标题实例详解 前言: 下午又找到了一个新的方法 这个方法不错 暂时没有发现异常的地方. 新写的App中需要使用UINavigationController对各个页面进行导航,但由于第一级页面的title较长,在进入第二级页面后返回按钮leftButtonItem的title就会变得很长,对NavigationBar空间占用很大,而且不美观,于是使用代码对leftButtonItem的title文本进行修改,无论是设置self.navigationItem.leftBa

原生JS实现 MUI导航栏透明渐变效果

mui内置有H5版本的透明渐变导航控件,教程参考mui官网:透明渐变导航是一种解决滚动条通顶的变通方案,相比双webview,具有更高的性能和更好的动画效果: 下面通过本文给大家分享基于原生JS实现 MUI导航栏透明渐变效果,具体内容详情如下所示: 首先声明:由于backgroundColor的值采用的是RGBA,IE8及以下不支持,所以此效果不支持IE8及以下的浏览器 css代码 body,p,h1{margin: 0;} .module-layer{ width: 100%; positio

微信小程序点击顶部导航栏切换样式代码实例

这篇文章主要介绍了微信小程序点击顶部导航栏切换样式代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 类似这样的效果 <view class='helpCateList'> <!-- 类别 --> <scroll-view class='scroll-view' scroll-x="true"> <view class="item-content" wx:key=&qu