Android高级UI开发(二十一)AppBarLayout与CollapsingToolbarLayout一分钟组合出视差效果

举报
yd_57386892 发表于 2020/12/29 01:21:45 2020/12/29
3.7k+ 0 0
【摘要】 今天继续看AppBarLayout的一个强大功能,那就是它结合CollapsingToolbarLayout可以1分钟作出我们常用的滑动视差效果,效果图如下: 1. 布局activity_main.xml 其实实现这个效果我们只需要配置布局文件即可,不需要写复杂的程序代码。接下来我们就来看一下这个神奇的布局文件,我们仍以MainActivity的activity_ma...

今天继续看AppBarLayout的一个强大功能,那就是它结合CollapsingToolbarLayout可以1分钟作出我们常用的滑动视差效果,效果图如下:

1. 布局activity_main.xml

其实实现这个效果我们只需要配置布局文件即可,不需要写复杂的程序代码。接下来我们就来看一下这个神奇的布局文件,我们仍以MainActivity的activity_main.xml布局为例:


      <android.support.design.widget.CoordinatorLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context=".MainActivity">
      <android.support.v4.widget.NestedScrollView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layout_behavior="@string/appbar_scrolling_view_behavior" >
      <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent" >
      <android.support.v7.widget.CardView
      android:layout_width="300dp"
      android:layout_height="200dp"
      android:layout_margin="0dp"
      app:cardCornerRadius="20dp"
      app:cardElevation="10dp"
      app:contentPadding="5dp" >
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:src="@drawable/image2" />
      </android.support.v7.widget.CardView>
      <android.support.v7.widget.CardView
      android:layout_width="300dp"
      android:layout_height="200dp"
      android:layout_margin="0dp"
      app:cardCornerRadius="20dp"
      app:cardElevation="10dp"
      app:contentPadding="5dp" >
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:src="@drawable/image2" />
      </android.support.v7.widget.CardView>
      <android.support.v7.widget.CardView
      android:layout_width="300dp"
      android:layout_height="200dp"
      android:layout_margin="0dp"
      app:cardCornerRadius="20dp"
      app:cardElevation="10dp"
      app:contentPadding="5dp" >
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:src="@drawable/image2" />
      </android.support.v7.widget.CardView>
      <android.support.v7.widget.CardView
      android:layout_width="300dp"
      android:layout_height="200dp"
      android:layout_margin="0dp"
      app:cardCornerRadius="20dp"
      app:cardElevation="10dp"
      app:contentPadding="5dp" >
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:src="@drawable/image2" />
      </android.support.v7.widget.CardView>
      <android.support.v7.widget.CardView
      android:layout_width="300dp"
      android:layout_height="200dp"
      android:layout_margin="0dp"
      app:cardCornerRadius="20dp"
      app:cardElevation="10dp"
      app:contentPadding="5dp" >
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:src="@drawable/image2" />
      </android.support.v7.widget.CardView>
      <android.support.v7.widget.CardView
      android:layout_width="300dp"
      android:layout_height="200dp"
      android:layout_margin="0dp"
      app:cardCornerRadius="20dp"
      app:cardElevation="10dp"
      app:contentPadding="5dp" >
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:src="@drawable/image2" />
      </android.support.v7.widget.CardView>
      <android.support.v7.widget.CardView
      android:layout_width="300dp"
      android:layout_height="200dp"
      android:layout_margin="0dp"
      app:cardCornerRadius="20dp"
      app:cardElevation="10dp"
      app:contentPadding="5dp" >
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:src="@drawable/image" />
      </android.support.v7.widget.CardView>
      </LinearLayout>
      </android.support.v4.widget.NestedScrollView>
      <android.support.design.widget.AppBarLayout
      android:layout_width="match_parent"
      android:layout_height="256dp"
      android:fitsSystemWindows="true">
      <android.support.design.widget.CollapsingToolbarLayout
      android:id="@+id/collapsing_toolbar_layout"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:contentScrim="#30469b"
      app:expandedTitleMarginBottom="100dp"
      app:expandedTitleMarginStart="100dp"
      app:layout_scrollFlags="scroll|exitUntilCollapsed">
      <ImageView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:scaleType="centerCrop"
      android:src="@drawable/image"
      app:layout_collapseMode="parallax"
      app:layout_collapseParallaxMultiplier="0.7"  />
      <android.support.v7.widget.Toolbar
      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
      android:id="@+id/toolbar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      app:layout_collapseMode="pin" />
      </android.support.design.widget.CollapsingToolbarLayout>
      </android.support.design.widget.AppBarLayout>
      </android.support.design.widget.CoordinatorLayout>
  
 

 实现了这个效果的过程是这样的:当我们上滑NestedScrollView的时候,AppBarLayout会控制CollapsingToolbarLayout不断让Imageview折叠,直到Toolbar的底部停止。在折叠的时候滑动界面往上移动的速度>Imageview折叠的速度,从而形成了视差效果。我们要为这些控件配置一些属性才能使它们相互配合起来。

1.1  NestedScrollView控件配置: 

      滑动部分,里面内嵌了足够长的控件(Cardview),与Scrollview一样可以滑动;

(1)app:layout_behavior="@string/appbar_scrolling_view_behavior属性:

        配置了app:layout_behavior="@string/appbar_scrolling_view_behavior属性,也就是指定了behavior,behavior用来捕获  NestedScrollView的滑动事件,并处理一些动画效果。这个behavior我们从名字来看它的来头不小,它正是AppbarLayout的一个内部类behavior.所以推测它可以处理appBarLayout内部包含的控件的动画效果,即我们的折叠视差效果。NestedScrollView控件所配置的behavior就是用来控制AppBarLayout内嵌的这个CollapsingToolbarLayout控件的行为,即让CollapsingToolbarLayout内嵌的折叠布局,这里是一张图片与NestedScrollView的滚动形成视差效果。

1.2 CollapsingToolbarLayout(折叠控件)控件配置:

 它里面嵌套了视差图片Imageview与Toolbar控件。它控制内嵌的Imageview的滑动视差效果。在这个例子中配置了如下属性:

 

 (1)app:contentScrim="#30469b"

        这个用以表示当滑动快到Toolbar的底部边缘时,正在滑动的imageview消失变成了一个色块布局,同时Toolbar的颜色也会            变成相同的颜色,这里是蓝色。

(2)app:expandedTitleMarginBottom="100dp",app:expandedTitleMarginStart="100dp"


       CollapsingToolbarLayout处于展开状态时,CollapsingToolbarLayout布局中的title的位置,距离CollapsingToolbarLayout的左边距是100dp,底部边距也是100dp。关于这个title的文本我们用程序代码去设置,见后面的MainActivity分析,当然我们也可以在CollapsingToolbarLayout XML标签里配置title文本.

(3)app:layout_scrollFlags="scroll|exitUntilCollapsed"

       这个属性决定了折叠动作。让内嵌的折叠布局(Imageivew)可以滑动,直到折叠效果完成(滑动到Toolbar的底边缘)隐藏Imageview. 在这里我们只看到了滑动,和什么时候隐藏,我们并没有看到任何关于视差效果的配置。视差效果的配置是在折叠布局里设置的,在这个例子中是一个Imageview。接下来我们就来看一下Imageview(折叠布局)是如何配置的。

1.3  折叠内容配置(这里是一个Imageview图片):

(1)app:layout_collapseMode="parallax" 这个用于配置折叠隐藏的速度。

      app:layout_collapseParallaxMultiplier="0.7" 这个是视差系数,就是折叠的速度。值越大Imagview折叠的速度越快,例如配置成2的效果是:当NestedScrollView还没有滑动到Toolbar附近,离Toolbar还有好长一段距离时,这时Imageview已经往下移动了好大一截,快要完全隐藏折叠的节奏。这里我们解释了Imageview如何配置成视差效果,我们再看看Toolbar配置了什么。

1.4  Toolbar的配置:


      app:layout_collapseMode="pin"
        表示当完全折叠时,Toolbar保持在顶端不动。
  
 

1. 5  总结

好了我们来总结一下这些配置,以便我们在后面修改这些配置来演示其它效果:

NestedScrollView

      app:layout_behavior="@string/appbar_scrolling_view_behavior  //behavior

CollapsingToolbarLayout:

      app:contentScrim="#30469b"        //Toolbar及底部附近的颜色。

      app:expandedTitleMarginBottom="100dp",      app:expandedTitleMarginStart="100dp" //下边距,左边距。

      app:layout_scrollFlags="scroll|exitUntilCollapsed"  //滚动且折叠完后整个折叠布局才隐藏。

Imageview:

  app:layout_collapseMode="parallax"     //这个就是视差效果。 app:layout_collapseParallaxMultiplier="0.7" 折叠布局折叠的速度。

2. MainActivity.java

第1节中activity_main.xml对应的程序代码


      package com.example.administrator.collapsingtoolbarlayout;
      import android.graphics.Color;
      import android.support.design.widget.CollapsingToolbarLayout;
      import android.support.v7.app.AppCompatActivity;
      import android.os.Bundle;
      import android.support.v7.widget.Toolbar;
      import android.view.View;
      public class MainActivity extends AppCompatActivity {
      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
      //Toolbar
      Toolbar toolbar;
       toolbar = (Toolbar)findViewById(R.id.toolbar);
       setSupportActionBar(toolbar);
       getSupportActionBar().setDisplayHomeAsUpEnabled(true);
       toolbar.setNavigationOnClickListener(new View.OnClickListener() {
      @Override
       public void onClick(View v) {
       onBackPressed();
       }
       });
      /*
       CollapsingToolbarLayout
       使用CollapsingToolbarLayout必须把title设置到CollapsingToolbarLayout上
       扩展title与折叠title会从白色随着滑动折叠自然过渡到绿色
       */
      CollapsingToolbarLayout mCollapsingToolbarLayout =
      (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout);
       mCollapsingToolbarLayout.setTitle("周星驰");
      //通过CollapsingToolbarLayout修改字体颜色
       mCollapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);//设置还没收缩时状态下字体颜色
       mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.GREEN);//设置收缩后Toolbar上字体的颜色
       }
      }
  
 

再上述代码里我们用代码 

mCollapsingToolbarLayout.setTitle("Colla");设置了CollapsingToolbarLayout布局在展开时的标题文本。
 

      setExpandedTitleColor与setCollapsedTitleTextColor分别设置了展开时与折叠时标题颜色的变化。
      这里它不会突然从白色变成绿色,而是有一个渐变的过程。在此你可能会想到是不是title也被分为展开时标题和折叠时文本,
      两个文本可以设置不同的内容,关于这些尝试性的改动及运行效果我们将在第3节中展示,第3节也会让您加深对各属性的理解。
      关于本文的第3节今日恐怕是没有时间了,以后再完善之。
  
 

依照惯例,还是给出当前阶段的源码下载地址:https://download.csdn.net/download/gaoxiaoweiandy/10973541

附录:

使用心得

这个app:layout_behavior="@string/appbar_scrolling_view_behavior" 其实就是

AppBarLayout.ScrollingViewBehavior类。
 

我们完全可以自定义Behavior,让其继承AppBarLayout.ScrollingViewBehavior,关于自定义behavior将在后面两篇文章讲解。这里贴出一个继承代码:


      package com.example.administrator.collapsingtoolbarlayout;
      import android.content.Context;
      import android.support.annotation.NonNull;
      import android.support.design.widget.AppBarLayout;
      import android.support.design.widget.CoordinatorLayout;
      import android.support.v4.view.ViewCompat;
      import android.util.AttributeSet;
      import android.util.Log;
      import android.view.View;
      import android.widget.Button;
      public class MyBehavior extends AppBarLayout.ScrollingViewBehavior {
      public MyBehavior(Context arg0, AttributeSet arg1) {
      super(arg0, arg1);
      // TODO Auto-generated constructor stub
       }
      @Override
      public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
      return (axes == ViewCompat.SCROLL_AXIS_VERTICAL)||super.onStartNestedScroll(coordinatorLayout, child, directTargetChild,
       target, axes);
       }
      @Override
      public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {
       Button btTest = coordinatorLayout.findViewById(R.id.btTest);
       Log.i("onNestedPreScroll","dy="+dy);
      if(dy > 20)
       {
      int color = coordinatorLayout.getContext().getResources().getColor(R.color.white);
       btTest.setBackground(null);
       btTest.setTextColor(color);
       }
      else if(dy < -20)
       {
      int color = coordinatorLayout.getContext().getResources().getColor(R.color.colorAccent);
       btTest.setBackground(null);
       btTest.setTextColor(color);
       }
      super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
       }
      }
  
 

这里是用于监听滑动事件的,其中以下代码表示监听垂直方向VERITCAL上的滑动。


          return (axes == ViewCompat.SCROLL_AXIS_VERTICAL)||super.onStartNestedScroll(coordinatorLayout, child, directTargetChild,
                      target, axes);
  
 

然后在onNestedPreScroll里对按钮btTest做了处理:改变颜色;同时AppBarLayout.ScrollingViewBehavior本身就自带了很多功能,结合折叠控件CollapsingToolbarLayout可以作出折叠视差效果,就是本篇所讲的视差效果。

2. 其它

发现一个demo里floatingActionButton里设置了这样一个属性

app:layout_anchor="@id/appbar"

app:layout_anchorGravity="bottom|right"

表示floatingActionButton与appbar关联在一起,并且浮动在appbar的右下角。

文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/87907558

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。