UC浏览器首页滑动动画实现

我们先来看下UC浏览器首页的滑动动画和我最终实现的动画效果




使用方式
<cn.ittiger.ucpage.view.UCIndexViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:ucindexview="http://schemas.android.com/apk/res-auto"android:id="@+id/ucindexview"android:layout_width="match_parent"android:layout_height="match_parent"ucindexview:pageHeadViewHeight="@dimen/dp_40"ucindexview:isPageHeadViewFixed="false"ucindexview:isContentHeadViewEnable="true"ucindexview:isPullRestoreEnable="false"ucindexview:contentHeadViewHeight="@dimen/dp_40"ucindexview:pageNavigationViewHeight="@dimen/dp_200"ucindexview:pageHeadViewLayoutId="@layout/page_head_view_layout"ucindexview:pageNavigationViewLayoutId="@layout/page_navigation_view_layout"ucindexview:contentHeadViewLayoutId="@layout/content_head_view_layout"ucindexview:contentViewLayoutId="@layout/content_view_layout"></cn.ittiger.ucpage.view.UCIndexView>

使用方式只需要如此布局即可,没有其他的任何代码操作,非常简单。几个重要属性如下:
1. isPageHeadViewFixed:设置PageHeadView是否固定显示(效果如上图2)
2. isContentHeadViewEnable:设置ContentHeadView是否启用(效果如上图3)
3. isPullRestoreEnable:设置是否可以通过下拉手势恢复到初始状态,UC首页下拉不能恢复初始状态
4. contentHeadViewHeight:设置contentHeadView视图的高度
5. pageNavigationViewHeight:设置PageNavigationView视图的高度
6. pageHeadViewLayoutId:设置PagetHeadView视图的内容布局,如图中的文字UC头条布局
7. pageNavigationViewLayoutId:设置PageNavigationView视图的内容布局,如图中的文字网址导航布局
8. contentHeadViewLayoutId:设置ContentHeadViev视图的内容布局,如图中的文字新闻头部导航布局
9. contentViewLayoutId:设置ContentView视图的内容布局,如图中的文字新闻内容区布局


github地址

实现及Demo地址:https://github.com/huyongli/UCIndexAnimation


下面来讲讲我的实现过程

首先来分析下UC首页这个动画中涉及到的元素和要点
  1. 向上滑动过程顶部的UC头条会慢慢的显示出来,我把这部分视图称为:PageHeadView(页面头部视图),很明显其初始化时是在屏幕外部的
  2. 向上滑动过程中UC漫站上面会有个新闻Tab菜单头部慢慢的显示出来,我把这部分视图称为:ContentHeadView(新闻头部视图),初始时是被ContentView遮盖,而后慢慢滑出,显然它的滑动速度是比ContentView快的
  3. 向上滑动过程中天气、搜索、网站导航会稍微往上滑动一段距离最终隐藏,我把这部分视图称为:PageNavigationView(页面导航视图),随着不断的滑动,会慢慢的被其余三个视图共同遮盖掉
  4. UC漫站整个新闻内容视图慢慢的向上滑动直至跟UC头条相接,我把这部分称为:ContentView(新闻内容视图)
  5. 根据动画效果来看,上面所说的四个不同的视图部分都是同时停止滑动,但是他们滑动的距离明显是不相同的
    • PageHeadView滑动的距离为其自身高度,
    • ContentHeadView的滑动距离为其自身高度与ContentView滑动的距离之和,而其相对ContentView视图的滑动距离为其自身高度
    • ContentView滑动距离为其自身初始距离顶部的边距减去 PageHeadViewContentHeadView两者的高度
    • PageNavigationView的滑动距离很小
  6. 上面的分析把UC首页整体划分成四个不同的View部分,另外其首页中只有ContentViewPageNavigationView两个视图会处理滑动事件

实现技术点和细节

根据上面的分析我们知道有三个视图是从被遮盖到显示或者是从显示到遮盖,剩下的ContentView一直是遮盖其他的视图。根据视图遮盖很容易联想到FrameLayout布局,多个FrameLayout布局叠加在一起就类似PS中的图层叠加,滑动可以看成是不同层级的FrameLayout的marginTop不断变化的过程。

实现类结构图

我的实现中先要说明两点:
1. 我把上滑称为展示状态或者叫Show状态
2. 下滑称为恢复初始化状态或者叫Hide状态

下图是我的实现类结构图:

主要类实现解析
  1. UCIndexView:模仿UC首页的最终实现,使用时在布局文件中使用此类即可
  2. PageHeadView、PageNavigationView、ContentView、ContentHeadView:这四个类的作用见我上面的分析
  3. MoveView:页面四个视图的基类,主要包含滑动过程中的一些基本属性和方法
    • mNeedMoveHeight:视图需要滑动的距离(ContentHeadView的此属性设置为相对ContentView的滑动距离),此属性主要用来计算各自视图在滑动过程中的步长
    • mShowStopMarginTop:视图进行Show操作时,当视图的marginTop值等于该值时,结束Show操作。此值用来确定上滑过程中,视图滑动结束时的位置。
    • mHideStopMarginTop:视图进行Hide操作时,当视图的marginTop值等于该值时,结束Hide操作。此值用来确定下滑过程中,视图滑动结束时的位置。通常此值为视图初始化成功后的marginTop值。
    • getMarginTop():获取视图当前的marginTop
    • updateMarginTop(flaot step):根据当前的滑动步长更新视图的marginTop
    • isHideFinish():判断当前视图的Hide操作是否完成
    • isShowFinish():判断当前视图的Show操作是否完成
    • getShowMoveStep(float step):获取视图Show过程中的实际可滑动步长,有可能计算得到的滑动步长超过了视图的可滑动距离
    • getHideMoveStep(float step):获取视图Hide过程中的实际可滑动步长,有可能计算得到的滑动步长超过了视图的可滑动距离
  4. TouchMoveView:用来处理手指触摸事件从而滑动的视图基类
滑动事件处理

直接上代码:

@Overridepublic void onTouchMoveEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mLastTouchY = event.getRawY();break;case MotionEvent.ACTION_MOVE://手指滑动过程中的滑动步长mDelY = event.getRawY() - mLastTouchY;viewMove(mDelY, mIsPullRestoreEnable);mLastTouchY = event.getRawY();break;case MotionEvent.ACTION_UP:int offset = 0;if(mDelY > 0) {//hide,下拉if(!mIsPullRestoreEnable) {//当前不允许下拉恢复return;}offset = mContentView.getHideOffset();} else {//show, 上拉offset = mContentView.getShowOffset();}if(offset <= mPageHeadView.getNeedMoveHeight() / 2) {//没有滑过二分之一高度slip(-mDelY, mIsPullRestoreEnable);} else {slip(mDelY, mIsPullRestoreEnable);}break;}}
/*** 对所有视图进行滑动操作* @param delY                  当前的滑动步长* @param isPullRestoreEnable   是否允许下拉恢复*/private void viewMove(float delY, boolean isPullRestoreEnable) {float step = Math.abs(delY);//根据滑动距离的比例计算PageHeadView的滑动步长float pageHeadViewStep = step * mPageHeadView.getNeedMoveHeight() / mContentView.getNeedMoveHeight();//手指滑动距离作为ContentView的滑动步长float contentViewStep = step;//ContentHeadView初始不固定显示时,其实际滑动步长为ContentView的滑动步长加上其相对ContentView的滑动步长float contentHeadViewStep = mIsContentHeadViewEnable ? step + step * mContentHeadView.getNeedMoveHeight() / mContentView.getNeedMoveHeight() : 0;float pageNavigationViewStep = step * mPageNavigationView.getNeedMoveHeight() / mContentView.getNeedMoveHeight();if(delY > 0) {//下滑if(!isPullRestoreEnable) {//当前不允许下拉恢复return;}if(!isHideFinish()) {//恢复状态是否已完成if(mIsPageHeadViewFixed == false) {mPageHeadView.onHideAnimation(pageHeadViewStep);}mContentView.onHideAnimation(contentViewStep);if(mIsContentHeadViewEnable) {mContentHeadView.onHideAnimation(contentHeadViewStep);}mPageNavigationView.onHideAnimation(pageNavigationViewStep);}} else {//上滑if(!isShowFinish()) {//展示状态是否已完成if(mIsPageHeadViewFixed == false) {//PageHeadView没有被固定时才进行滑动mPageHeadView.onShowAnimation(pageHeadViewStep);}mContentView.onShowAnimation(contentViewStep);if(mIsContentHeadViewEnable) {//ContentHeadView启用时才进行滑动mContentHeadView.onShowAnimation(contentHeadViewStep);}mPageNavigationView.onShowAnimation(pageNavigationViewStep);}}}
/*** 手指松开屏幕后,视图自动滑动* 每隔 mAutoSlipTimeStep 长时间滑动 mAutoSlipStep 距离* @param delY  当前的滑动距离*  @param isPullRestoreEnable   是否允许下拉恢复*/
private void slip(float delY, final boolean isPullRestoreEnable) {if(delY > 0) {//当前滑动为向下滑动,即处于恢复状态if(isHideFinish()) {//已经恢复结束return;}postDelayed(new Runnable() {@Overridepublic void run() {viewMove(mAutoSlipStep, isPullRestoreEnable);slip(mAutoSlipStep, isPullRestoreEnable);//准备下一次滑动}}, mAutoSlipTimeStep);} else {//当前滑动为向上滑动,即处于展示状态if(isShowFinish()) {//已经展示结束return;}postDelayed(new Runnable() {@Overridepublic void run() {viewMove(-mAutoSlipStep, isPullRestoreEnable);slip(-mAutoSlipStep, isPullRestoreEnable);//准备下一次滑动}}, mAutoSlipTimeStep);}
}

上面的代码中我把手指每次的滑动距离当做ContentView的滑动步长,再根据ContentView的滑动步长计算其他视图的当前滑动步长,计算具体方式可以看代码中的注释。

其实上面代码里的实现步骤还是比较清晰简单的,主要是如下几个步骤:

  1. 在MotionEvent.MOVE中先得到当前手指滑动的距离,此距离作为ContentView的此次滑动步长
    根据ContentView的滑动步长计算其他三个视图的滑动步长
  2. 根据当前是上滑还是下滑,判断是否滑动结束,没有结束则按照计算得到的步长继续对View进行滑动处理
  3. 当手指松开后,在MotionEvent.UP中判断ContentView的滑动距离是否达到了PageHeadView高度的一半,从而决定是继续同方向滑动至结束还是恢复到原状态
  4. 手指松开后,最终调用slip方法开始自动循环滑动处理,直至滑动结束

UC浏览器首页滑动动画实现相关推荐

  1. Behavior实现UC浏览器首页动画效果

    老规矩,还是先上效果图 github地址 前面我也写过一篇关于UC浏览器首页滑动动画效果的文章UC浏览器首页滑动动画实现,只不过这篇文章是通过自定义View的方式实现这个滑动效果.最近在看Behavi ...

  2. android 高仿UC浏览器首页上拉面板效果

    最近在项目中,产品经理看见uc浏览器首页的上拉面板的效果做的非常不错,于是希望我们的项目的首页也做成这样的效果.于是经过思考后,实现了一个仿uc浏览器的上拉面板效果. 接下来说一下实现的思路吧 . 首 ...

  3. uc如何HTML编辑,UC浏览器首页这些快捷网址导航如何编辑,怎么修..._网络编辑_帮考网...

    在UC浏览器打开下拉菜单后,找到"设置"这个按钮,点击打开,在"常规"里面有一个"浏览器主页保护"找到这个,你不管它当时是怎么设置的,你现在 ...

  4. android仿微信红包动画、Kotlin综合应用、Xposed模块、炫酷下拉视觉、UC浏览器滑动动画等源码...

    Android精选源码 仿微信打开红包旋转动画 使用Kotlin编写的Android应用,内容你想象不到 Android手机上的免Root Android系统日志Viewer 一个能让微信 Mater ...

  5. android仿微信红包动画、Kotlin综合应用、Xposed模块、炫酷下拉视觉、UC浏览器滑动动画等源码

    Android精选源码 仿微信打开红包旋转动画 使用Kotlin编写的Android应用,内容你想象不到 Android手机上的免Root Android系统日志Viewer 一个能让微信 Mater ...

  6. 自定义Behavior的艺术探索-仿UC浏览器主页

    出处:http://www.jianshu.com/p/f7989a2a3ec2 前言&效果预览 最近几个周末基本在研究CoordinatorLayout控件和自定义Behavior当中,这期 ...

  7. 尝试写个UC浏览器(堆叠视图A)

    背景:快过年了,问题那个多呀,最近手都敲出老茧了,上班打个卡都要识别几分钟,不知道身为程序猿的你是不是有同样的感受.唉,不说了,老子名下还有200多个bug... 既然前面已经吹了两次逼( 布局篇 和 ...

  8. 仿oppo手机浏览器首页的滑动布局

    仿oppo手机浏览器首页的滑动布局 原效果图 我大概实现的样子 这个其实主要是一些事件分发的一些处理 周末的午后,我悠然的躺着床上,甚是无聊,拿起我的oppo手机,打开浏览器准备输入我熟悉的xxx . ...

  9. android 语音搜索动画,Android自定义控件实现UC浏览器语音搜索效果

    最近项目上要实现语音搜索功能,界面样式要模仿一下UC浏览器的样式,UC浏览器中有一个控件,会随着声音大小浮动,然后寻思偷个懒,百度一下,结果也没有找到类似的,只能自己动手了. 先上图看我实现的效果: ...

最新文章

  1. 新书上市 | 《复分析:可视化方法》
  2. 企业创新管理的八大误区
  3. 关于SQL Server 2017中使用json传参时解析遇到的多层解析问题
  4. 减少过敏反应的生活细节
  5. 使用SpringBoot的jackson包进行实体类型转换
  6. Acwing第 28 场周赛【完结】
  7. php 正则匹配字母和数字,正则匹配密码只能是数字和字母组合字符串功能【php与js实现】...
  8. kotlin 编译时常量_Kotlin程序| 编译时常量示例
  9. 网页粒子背景插件 -Canvas-nest.js
  10. Tripwire安装
  11. 计算机组成原理CRC相关运算,计算机专业基础综合计算机组成原理(数据的表示和运算)-试卷1...
  12. canvas贝塞尔曲线爱心_HTML5 Canvas 绘制贝塞尔曲线 Bezier and quadratic curves
  13. 多线段几何图形—— 简单几何图形(获取一个在图形内部的点)
  14. Google seo图片优化技巧
  15. 彻底卸载Xubuntu Kubuntu
  16. RT Preempt Linux简介
  17. 即食水产消费品公司“不等食品”获千万元级A轮融资,险峰长青领投...
  18. 数字经济与数字化转型
  19. Vue + D3 动态可视化图实现之一:折线图
  20. 【天光学术】物流工程论文:连锁超市缺货和爆仓库存问题改善分析(节选)

热门文章

  1. spring MVC从零开始
  2. typec耳机知识介绍
  3. 基于服务器端的三维渲染技术
  4. ai替换混合轴例子_可解释的vs可解释的AI:一个直观的例子
  5. 泰语翻译成中文,常用的入境交通类词汇有哪些?
  6. Python人脸识别图片视频
  7. 躲开混脸熟的车型,一文带你去看2019上海车展里的新面孔
  8. 彩色模型RGB,HSI,HSV,CMYK区分
  9. mysql 把表名改成大写_mysql将表名改成大写的实例
  10. 计算机辅助医疗未来展望,数字骨科应用与展望:更精确、个性、直观的未来前景...