Android5.0推出的MaterialDesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的。如此一来,一方面导航栏能够放得下更多控件,另一方面在用户想看具体内容时也能腾出更多的屏幕空间。

这么说可能比较抽象,那就先来看看两张导航栏的效果图,第一张是导航栏完全展开时的界面,此时页面头部的导航栏占据了较大部分的高度;

第二张是导航栏完全收缩时的界面,此时头部导航栏只剩矮矮的一个长条。

看起来很眼熟是不是,上面的截图正是仿支付宝首页的头部效果。如果你熟悉AppBarLayout和CollapsingToolbarLayout的话,也许可以很快做出类似以上的简单界面,具体地说,就是定义一个CoordinatorLayout嵌套AppBarLayout再嵌套CollapsingToolbarLayout再嵌套Toolbar的布局。之所以要嵌套这么多层,是因为要完成以下功能:
1、CoordinatorLayout嵌套AppBarLayout,这是为了让头部导航栏能够跟随内容视图下拉而展开,跟随内容视图上拉而收缩。这个内容视图可以是RecyclerView,也可以是NestedScrollView;
2、AppBarLayout嵌套CollapsingToolbarLayout,这是为了定义导航栏下面需要展开和收缩的部分视图;
3、CollapsingToolbarLayout嵌套Toolbar,这是为了定义导航栏上方无论何时都要显示的长条区域,其中Toolbar还要定义两个不同的样式布局,用于分别显示展开与收缩状态时的工具栏界面。

下面是基于以上思路实现的布局文件代码:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true" ><android.support.design.widget.AppBarLayoutandroid:id="@+id/abl_bar"android:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true" ><android.support.design.widget.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"app:contentScrim="@color/blue_dark" ><includeandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="@dimen/toolbar_height"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7"layout="@layout/life_pay" /><android.support.v7.widget.Toolbarandroid:layout_width="match_parent"android:layout_height="@dimen/toolbar_height"app:layout_collapseMode="pin"app:contentInsetLeft="0dp"app:contentInsetStart="0dp" ><includeandroid:id="@+id/tl_expand"android:layout_width="match_parent"android:layout_height="match_parent"layout="@layout/toolbar_expand" /><includeandroid:id="@+id/tl_collapse"android:layout_width="match_parent"android:layout_height="match_parent"layout="@layout/toolbar_collapse"android:visibility="gone" /></android.support.v7.widget.Toolbar></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/rv_content"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="10dp"app:layout_behavior="@string/appbar_scrolling_view_behavior" /></android.support.design.widget.CoordinatorLayout>

然而仅仅实现上述布局并非万事大吉,支付宝首页的头部在伸缩时可是有动画效果的,就像下面这个动图那样有淡入淡出的渐变动画:

这个渐变动画其实可分为两段:
1、导航栏从展开状态向上收缩时,头部的各控件要慢慢向背景色过渡,也就是淡入效果;
2、导航栏向上收缩到一半,顶部的工具栏要换成收缩状态下的工具栏布局,并且随着导航栏继续向上收缩,新工具栏上的各控件也要慢慢变得清晰起来,也就是淡出效果。
如果导航栏是从收缩状态向下展开,则此时相应的做上述渐变动画的取反效果,即:
1、导航栏从收缩状态向下展开时,头部的各控件要慢慢向背景色过渡,也就是淡入效果;同时展开导航栏的下部分布局,并且该布局上的各控件渐渐变得清晰;
2、导航栏向下展开到一半,顶部的工具栏要换成展开状态下的工具栏布局,并且随着导航栏继续向下展开,新工具栏上的各控件也要慢慢变得清晰起来,也就是淡出效果。

看起来还比较复杂,如果只对某个控件做渐变动画还好,可是导航栏上的控件有好几个,而且并不固定常常会增加和修改。倘若要对导航栏上的各控件逐一动画过去,不但费力气,而且后期也不好维护。为了解决这个问题,我们可以采取类似遮罩的做法,即一开始先给导航栏罩上一层透明的视图,此时导航栏的画面就完全显示;然后随着导航栏的移动距离,计算当前位置下的遮罩透明度,比如该遮罩变得越来越不透明,看起来导航栏就像蒙上了一层面纱,蒙到最后就看不见了。反过来,也可以一开始给导航栏罩上一层不透明的视图,此时导航栏的控件是看不见的,然后随着距离的变化,遮罩变得越来越不透明,导航栏也会跟着变得越来越清晰了。

渐变动画的思路有了,可谓万事俱备,只欠东风,再来一个导航栏的移动偏移监听器便行,正好有个现成的AppBarLayout.OnOffsetChangedListener,只需给AppBarLayout对象调用addOnOffsetChangedListener方法,即可实现给导航栏注册偏移监听器的功能。接下来的事还是直接看看具体的实现代码吧:

public class AlipayActivity extends AppCompatActivity implements OnOffsetChangedListener {private final static String TAG = "AlipayActivity";private AppBarLayout abl_bar;private View tl_expand, tl_collapse;private View v_expand_mask, v_collapse_mask, v_pay_mask;private int mMaskColor;private RecyclerView rv_content;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_alipay);mMaskColor = getResources().getColor(R.color.blue_dark);rv_content = (RecyclerView) findViewById(R.id.rv_content);rv_content.setLayoutManager(new GridLayoutManager(this, 4));rv_content.setAdapter(new LifeAdapter(this, LifeItem.getDefault()));abl_bar = (AppBarLayout) findViewById(R.id.abl_bar);tl_expand = (View) findViewById(R.id.tl_expand);tl_collapse = (View) findViewById(R.id.tl_collapse);v_expand_mask = (View) findViewById(R.id.v_expand_mask);v_collapse_mask = (View) findViewById(R.id.v_collapse_mask);v_pay_mask = (View) findViewById(R.id.v_pay_mask);abl_bar.addOnOffsetChangedListener(this);}@Overridepublic void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {Log.d(TAG, "verticalOffset="+verticalOffset);int offset = Math.abs(verticalOffset);int total = appBarLayout.getTotalScrollRange();int alphaIn = offset;int alphaOut = (200-offset)<0?0:200-offset;int maskColorIn = Color.argb(alphaIn, Color.red(mMaskColor),Color.green(mMaskColor), Color.blue(mMaskColor));int maskColorInDouble = Color.argb(alphaIn*2, Color.red(mMaskColor),Color.green(mMaskColor), Color.blue(mMaskColor));int maskColorOut = Color.argb(alphaOut*2, Color.red(mMaskColor),Color.green(mMaskColor), Color.blue(mMaskColor));if (offset <= total / 2) {tl_expand.setVisibility(View.VISIBLE);tl_collapse.setVisibility(View.GONE);v_expand_mask.setBackgroundColor(maskColorInDouble);} else {tl_expand.setVisibility(View.GONE);tl_collapse.setVisibility(View.VISIBLE);v_collapse_mask.setBackgroundColor(maskColorOut);}v_pay_mask.setBackgroundColor(maskColorIn);}}

点此查看Android开发笔记的完整目录

__________________________________________________________________________
本文现已同步发布到微信公众号“老欧说安卓”,打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。

Android开发笔记(一百四十四)高仿支付宝的头部伸缩动画相关推荐

  1. Android开发笔记(五十四)数据共享接口ContentProvider

    ContentProvider 前面几节介绍了进程间通信的几种方式,包括消息包级别的Messenger.接口调用级别的AIDL.启动页面/服务级别的Notification,还有就是本节这个数据库级别 ...

  2. Android开发笔记(七十四)布局文件优化

    include/merge 布局优化中常常用到include/merge标签,include的含义类似C代码中的include,意思是直接把指定布局片段包含进当前的布局文件.include适用于多个布 ...

  3. Android开发笔记(二十四)res目录的结构与配置

    res目录结构 res是Android项目工程中存放各类的目录,主要包括布局.图形与配置等等.res的子目录主要有: anim : 存放动画的描述文件 drawable : 存放各类图形的描述文件,包 ...

  4. Android开发笔记(八十四)使用Properties读写属性值

    Properties概述 Java中的配置文件常为.properties文件,而Properties类便是读写此类文件的工具.属性文件有两种格式,一种是文本格式,其内容是"键=值" ...

  5. Android开发笔记(六十四)网页加载与JS调用

    内置浏览器 网页视图WebView 如果一个网站已经有现成的网页及业务逻辑,那么使用WebView将其内嵌到app中,省去了app重画页面与http通信的事情,无疑是更经济的做法.WebView就是A ...

  6. Android开发笔记(三十四)Excel文件的读写

    Android中操作Excel文件的场合较少见,主要是一些专业领域导入导出报表时使用,所以处理Excel读写的开源代码也很稀缺.目前读写Excel主要采用开源库jxl,这个是韩国人写的excel操作工 ...

  7. Android开发笔记(八十九)单例模式

    基本概念 单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,从而方便对实例个数的控制并节约系统资源. 单例模式有三个特点: 1.某个类只能有一个实例: 2.它要自行创建这个实例: 3.它只有 ...

  8. Android开发笔记(八十六)几个特殊的类

    接口interface interface是一些功能的集合,但它只定义了对象必须实现的成员,而不包含成员的实现代码,成员的具体代码由实现接口的类提供.Android对接口的使用场景主要有三类:事件监听 ...

  9. Android开发笔记(五十九)巧用传感器

    传感器Sensor 传感器是Android用来感知周围环境以及运动信息的工具.因为具体的感应信息依赖于相关硬件,所以虽然Android提供了众多的感应器,但不是每部手机都能支持这么多感应器,恰恰相反, ...

最新文章

  1. 现在的教育:感慨之一
  2. java只会用不知道原理6_程序员面试宝典之14道初级Java面试题分享
  3. Spring-AOP @AspectJ语法基础
  4. python中csv库_关于python 自带csv库的使用心得 附带操作实例以及excel下乱码的解决...
  5. 变电所自动化系统的电源配置
  6. java中之内存溢出说明
  7. sql server2008用ip远程连接,解决默认连不上的问题
  8. iOS网络请求之multipart/form-data提交数据
  9. idm chrome扩展被阻止解决办法
  10. 机械类常用英语(一.组装、冲压、喷漆等专业词汇)
  11. tiny yolov3 海思_yolov3及tiny版本的实践(Windows)
  12. SequelizeAccessDeniedError的原因和解决方式
  13. 多线程服务器的常用编程模型
  14. MATLAB函数——fir1
  15. 定积分的概念及可积条件
  16. 【自然语言处理-2】word2vec词嵌入算法“男人”+“女人”=“爱情的坟墓”
  17. 【DBA】 Oracle 学习路线
  18. 在线制作banner的网站
  19. 解读CUDA Compiler Driver NVCC - Ch.1 - Introduction
  20. xfs文件系统恢复工具xfs_undelete

热门文章

  1. 人工智能作业考试汇总
  2. CN笔记:第三章 链路层
  3. 最短路算法(3种算法)
  4. 541页《利用Python进行数据分析》分享(附源码下载)
  5. STM32常见错误error: #268: declaration may not appear after executable statement
  6. 图解系列之JAVA执行过程
  7. 译-使用Scroll Snapping实现CSS控制页面滚动
  8. 吴恩达机器学习 逻辑回归 作业3(手写数字分类) Python实现 代码详细解释
  9. Mysql更新计数器_MySQL实现计数器如何在高并发场景下更新并保持数据正确性
  10. centos6安装python_如何在CentOS6上安装Python2.7和Python3.3