欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android仿支付宝的头部伸缩动画效果

程序员文章站 2023-12-01 11:47:04
android5.0推出的materialdesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的。如此一来,一方面导航栏能够放得...

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

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

Android仿支付宝的头部伸缩动画效果

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

Android仿支付宝的头部伸缩动画效果

看起来很眼熟是不是,上面的截图正是仿支付宝首页的头部效果。如果你熟悉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.appbarlayout 
    android:id="@+id/abl_bar" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:fitssystemwindows="true" > 
    <android.support.design.widget.collapsingtoolbarlayout 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:fitssystemwindows="true" 
      app:layout_scrollflags="scroll|exituntilcollapsed|snap" 
      app:contentscrim="@color/blue_dark" > 
      <include 
        android: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.toolbar 
        android:layout_width="match_parent" 
        android:layout_height="@dimen/toolbar_height" 
        app:layout_collapsemode="pin" 
        app:contentinsetleft="0dp" 
        app:contentinsetstart="0dp" > 
        <include 
          android:id="@+id/tl_expand" 
          android:layout_width="match_parent" 
          android:layout_height="match_parent" 
          layout="@layout/toolbar_expand" /> 
        <include 
          android: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.recyclerview 
    android: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> 

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

Android仿支付宝的头部伸缩动画效果

这个渐变动画其实可分为两段:

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; 
  @override 
  protected 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); 
  } 
  @override 
  public 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仿支付宝的头部伸缩动画效果,希望对大家有所帮助