Android CoordinatorLayout+AppBarLayout实现toolbar背景渐变透明

本文转载于:https://blog.csdn.net/qq402164452/article/details/53760203
现在很多APP上面都有滚动视图使顶部的Toolbar背景透明度渐变的效果,这种需求有两种实现方式,一种是自定义一个ViewGroup,通过监听scroll或者recyclerview的滚动高度来改变透明度,一种是使用 CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout来实现,因为CoordinatorLayout 有Behavior对象,可以通过设置来达到折叠效果。

效果图:

这里写图片描述

build.gradle配置:
首先在 dependencies中引入 design依赖包

compile 'com.android.support:design:24.2.0'
compile 'com.android.support:recyclerview-v7:24.+'
compile 'com.android.support:appcompat-v7:24.2.0'
  
  
  • 1
  • 2
  • 3

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<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:background="@color/default_background">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/AppFragment_AppBarLayout"
        android:layout_width="match_parent"
        android:layout_height="250dp"<!--AppBarLayout必须设置固定高度-->
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/AppFragment_CollapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"<!--设置可滚动并且折叠在顶部-->
            app:contentScrim="?attr/colorPrimary">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/app_banner_img"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"/><!--设置视差模式-->

            <android.support.v7.widget.Toolbar
                android:id="@+id/AppFragment_Toolbar"
                android:layout_width="match_parent"
                android:layout_height="76dp"
                android:background="@color/colorPrimary"
                app:layout_collapseMode="pin"><!--设置固定在顶部-->

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:gravity="center"
                    android:paddingTop="20dp"  <!--系统状态栏高度-->
                    android:text="应用"
                    android:textColor="@android:color/white"
                    android:textSize="@dimen/Toolbar_textSize" />

            </android.support.v7.widget.Toolbar>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/AppFragment_recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <!--RecyclerView滚动行为-->

</android.support.design.widget.CoordinatorLayout>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

Activity中设置状态栏透明:

@Override
    public void onCreate(Bundle savedInstancedState){
        setContentView(R.layout.activity_main);
        super.onCreate(savedInstancedState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

根据百分比去获取ARGB (透明度,红色,绿色,蓝色)颜色值:

/** 根据百分比改变颜色透明度 */
    public int changeAlpha(int color, float fraction) {
        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        int alpha = (int) (Color.alpha(color) * fraction);
        return Color.argb(alpha, red, green, blue);
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

监听AppBarLayout的滚动变化OnOffsetChangedListener来改变Toolbar的背景透明度颜色:

mAppBarLayout= (AppBarLayout) view.findViewById(R.id.AppFragment_AppBarLayout);
mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {  
     mToolbar.setBackgroundColor(changeAlpha(getResources().getColor(R.color.colorPrimary),Math.abs(verticalOffset*1.0f)/appBarLayout.getTotalScrollRange()));
            }
        });
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset)的第二个参数是AppBarLayout的Y轴偏移量,当AppBarLayout处于扩展状态时,verticalOffset=0;当AppBarLayout处于折叠状态时,verticalOffset=-appBarLayout.getTotalScrollRange(),注意是负的;当处于滚动状态时,verticalOffset 从0 到 负的appBarLayout.getTotalScrollRange()之间变化,所以这里使用Math.abs来取绝对值。当向上滚动时,Math.abs(verticalOffset*1.0f)越来越大,向下滚动时,Math.abs(verticalOffset*1.0f)越来越小,通过Math.abs(verticalOffset*1.0f)/appBarLayout.getTotalScrollRange() 计算偏移量的百分比来改变Toolbar背景透明度。

下面介绍一下CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout的一些用法:

CoordinatorLayout

CoordinatorLayout继承FrameLayout,CoordinatorLayout有调度协调子布局的能力,CoordinatorLayout使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果。CoordinatorLayout通过设置子View的 Behaviors来调度子View。系统(Support V7)提供了AppBarLayout.Behavior, AppBarLayout.ScrollingViewBehavior, FloatingActionButton.Behavior, SwipeDismissBehavior;V extends View; 等。

为了使AppBarLayout可以滚动,CoordinatorLayout必须带有一个可滚动的子View,这个子View必须实现NestedScrollingChild接口,目前实现这个接口的有RecyclerView和NestedScrollView(是一个ScrollView,里面只能包含一个子View)。CoordinatorLayout包含的子视图中带有滚动属性的View需要设置app:layout_behavior属性。上述例子中的RecyclerView就添加了一个behavior属性
app:layout_behavior=”@string/appbar_scrolling_view_behavior”

AppBarLayout

AppBarLayout继承LinearLayout,在 AppBarLayout里面的子View有app:layout_scrollFlags 属性来控制AppBarLayout滑动时子View的效果。

app:layout_scrollFlags有四个值:
scroll: 所有想滚动出屏幕的view都需要设置这个flag, 没有设置这个flag的view将被固定在屏幕顶部。例如,TabLayout 没有设置这个值,将会停留在屏幕顶部。
enterAlways: 设置这个flag时,向下的滚动都会导致该view变为可见,启用快速“返回模式”。
enterAlwaysCollapsed: 当你的视图已经设置minHeight属性又使用此标志时,你的视图只能已最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。
exitUntilCollapsed: 滚动退出屏幕,最后折叠在顶端。
不设置app:layout_scrollFlags时默认是不滚动的 固定在那里。

CollapsingToolbarLayout

CollapsingToolbarLayout继承FrameLayout,CollapsingToolbarLayout可实现折叠效果。
CollapsingToolbarLayout有一个重要的属性app:layout_collapseMode来控制子View的折叠模式:

CollapseMode :子视图的折叠模式,在子视图设置,有两种模式。
1“pin”:固定模式,在折叠的时候最后固定在顶端;
2“parallax”:视差模式,在折叠的时候会有个视差折叠的效果。可以在布局中使用属性app:layout_collapseMode=”parallax”来改变。

其他一些属性:
1. Collapsing title:ToolBar的标题,当CollapsingToolbarLayout全屏没有折叠时,title显示的是大字体,在折叠的过程中,title不断变小到一定大小的效果。你可以调用setTitle(CharSequence)方法设置title。
2. Content scrim:ToolBar被折叠到顶部固定时候的背景,你可以调用setContentScrim(Drawable)方法改变背景或者 在属性中使用 app:contentScrim=”?attr/colorPrimary”来改变背景。
3. Status bar scrim:状态栏的背景,调用方法setStatusBarScrim(Drawable)。还没研究明白,不过这个只能在Android5.0以上系统有效果。
4. Parallax scrolling children:CollapsingToolbarLayout滑动时,子视图的视觉差,可以通过属性app:layout_collapseParallaxMultiplier=”0.6”改变。值de的范围[0.0,1.0],值越大视察越大。
5. layout_anchor 的属性,连同 layout_anchorGravity 一起,可以用来放置与其他视图关联在一起的悬浮视图(如 FloatingActionButton)。

注意事项

CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout联合一起使用时,有一些注意点:

  1. CoordinatorLayout作为布局的父布局容器。
  2. AppBarLayout中给需要滑动的组件设置 app:layout_scrollFlags属性。
  3. CoordinatorLayout中给滑动的组件设置app:layout_behavior属性
  4. AppBarLayout的高度固定,不能用match_parent,使用wrap_content时子view必须设置固定高度
  5. CollapsingToolbarLayout的子视图设置layout_collapseMode属性
  6. 关联悬浮视图设置app:layout_anchor,app:layout_anchorGravity属性

现在很多APP上面都有滚动视图使顶部的Toolbar背景透明度渐变的效果,这种需求有两种实现方式,一种是自定义一个ViewGroup,通过监听scroll或者recyclerview的滚动高度来改变透明度,一种是使用 CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout来实现,因为CoordinatorLayout 有Behavior对象,可以通过设置来达到折叠效果。
效果图:
这里写图片描述

build.gradle配置:
首先在 dependencies中引入 design依赖包

compile 'com.android.support:design:24.2.0'
compile 'com.android.support:recyclerview-v7:24.+'
compile 'com.android.support:appcompat-v7:24.2.0'
  
  
  • 1
  • 2
  • 3

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<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:background="@color/default_background">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/AppFragment_AppBarLayout"
        android:layout_width="match_parent"
        android:layout_height="250dp"<!--AppBarLayout必须设置固定高度-->
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/AppFragment_CollapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"<!--设置可滚动并且折叠在顶部-->
            app:contentScrim="?attr/colorPrimary">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/app_banner_img"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"/><!--设置视差模式-->

            <android.support.v7.widget.Toolbar
                android:id="@+id/AppFragment_Toolbar"
                android:layout_width="match_parent"
                android:layout_height="76dp"
                android:background="@color/colorPrimary"
                app:layout_collapseMode="pin"><!--设置固定在顶部-->

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:gravity="center"
                    android:paddingTop="20dp"  <!--系统状态栏高度-->
                    android:text="应用"
                    android:textColor="@android:color/white"
                    android:textSize="@dimen/Toolbar_textSize" />

            </android.support.v7.widget.Toolbar>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/AppFragment_recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <!--RecyclerView滚动行为-->

</android.support.design.widget.CoordinatorLayout>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

Activity中设置状态栏透明:

@Override
    public void onCreate(Bundle savedInstancedState){
        setContentView(R.layout.activity_main);
        super.onCreate(savedInstancedState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

根据百分比去获取ARGB (透明度,红色,绿色,蓝色)颜色值:

/** 根据百分比改变颜色透明度 */
    public int changeAlpha(int color, float fraction) {
        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        int alpha = (int) (Color.alpha(color) * fraction);
        return Color.argb(alpha, red, green, blue);
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

监听AppBarLayout的滚动变化OnOffsetChangedListener来改变Toolbar的背景透明度颜色:

mAppBarLayout= (AppBarLayout) view.findViewById(R.id.AppFragment_AppBarLayout);
mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {  
     mToolbar.setBackgroundColor(changeAlpha(getResources().getColor(R.color.colorPrimary),Math.abs(verticalOffset*1.0f)/appBarLayout.getTotalScrollRange()));
            }
        });
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset)的第二个参数是AppBarLayout的Y轴偏移量,当AppBarLayout处于扩展状态时,verticalOffset=0;当AppBarLayout处于折叠状态时,verticalOffset=-appBarLayout.getTotalScrollRange(),注意是负的;当处于滚动状态时,verticalOffset 从0 到 负的appBarLayout.getTotalScrollRange()之间变化,所以这里使用Math.abs来取绝对值。当向上滚动时,Math.abs(verticalOffset*1.0f)越来越大,向下滚动时,Math.abs(verticalOffset*1.0f)越来越小,通过Math.abs(verticalOffset*1.0f)/appBarLayout.getTotalScrollRange() 计算偏移量的百分比来改变Toolbar背景透明度。

下面介绍一下CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout的一些用法:

CoordinatorLayout

CoordinatorLayout继承FrameLayout,CoordinatorLayout有调度协调子布局的能力,CoordinatorLayout使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果。CoordinatorLayout通过设置子View的 Behaviors来调度子View。系统(Support V7)提供了AppBarLayout.Behavior, AppBarLayout.ScrollingViewBehavior, FloatingActionButton.Behavior, SwipeDismissBehavior;V extends View; 等。

为了使AppBarLayout可以滚动,CoordinatorLayout必须带有一个可滚动的子View,这个子View必须实现NestedScrollingChild接口,目前实现这个接口的有RecyclerView和NestedScrollView(是一个ScrollView,里面只能包含一个子View)。CoordinatorLayout包含的子视图中带有滚动属性的View需要设置app:layout_behavior属性。上述例子中的RecyclerView就添加了一个behavior属性
app:layout_behavior=”@string/appbar_scrolling_view_behavior”

AppBarLayout

AppBarLayout继承LinearLayout,在 AppBarLayout里面的子View有app:layout_scrollFlags 属性来控制AppBarLayout滑动时子View的效果。

app:layout_scrollFlags有四个值:
scroll: 所有想滚动出屏幕的view都需要设置这个flag, 没有设置这个flag的view将被固定在屏幕顶部。例如,TabLayout 没有设置这个值,将会停留在屏幕顶部。
enterAlways: 设置这个flag时,向下的滚动都会导致该view变为可见,启用快速“返回模式”。
enterAlwaysCollapsed: 当你的视图已经设置minHeight属性又使用此标志时,你的视图只能已最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。
exitUntilCollapsed: 滚动退出屏幕,最后折叠在顶端。
不设置app:layout_scrollFlags时默认是不滚动的 固定在那里。

CollapsingToolbarLayout

CollapsingToolbarLayout继承FrameLayout,CollapsingToolbarLayout可实现折叠效果。
CollapsingToolbarLayout有一个重要的属性app:layout_collapseMode来控制子View的折叠模式:

CollapseMode :子视图的折叠模式,在子视图设置,有两种模式。
1“pin”:固定模式,在折叠的时候最后固定在顶端;
2“parallax”:视差模式,在折叠的时候会有个视差折叠的效果。可以在布局中使用属性app:layout_collapseMode=”parallax”来改变。

其他一些属性:
1. Collapsing title:ToolBar的标题,当CollapsingToolbarLayout全屏没有折叠时,title显示的是大字体,在折叠的过程中,title不断变小到一定大小的效果。你可以调用setTitle(CharSequence)方法设置title。
2. Content scrim:ToolBar被折叠到顶部固定时候的背景,你可以调用setContentScrim(Drawable)方法改变背景或者 在属性中使用 app:contentScrim=”?attr/colorPrimary”来改变背景。
3. Status bar scrim:状态栏的背景,调用方法setStatusBarScrim(Drawable)。还没研究明白,不过这个只能在Android5.0以上系统有效果。
4. Parallax scrolling children:CollapsingToolbarLayout滑动时,子视图的视觉差,可以通过属性app:layout_collapseParallaxMultiplier=”0.6”改变。值de的范围[0.0,1.0],值越大视察越大。
5. layout_anchor 的属性,连同 layout_anchorGravity 一起,可以用来放置与其他视图关联在一起的悬浮视图(如 FloatingActionButton)。

注意事项

CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout联合一起使用时,有一些注意点:

  1. CoordinatorLayout作为布局的父布局容器。
  2. AppBarLayout中给需要滑动的组件设置 app:layout_scrollFlags属性。
  3. CoordinatorLayout中给滑动的组件设置app:layout_behavior属性
  4. AppBarLayout的高度固定,不能用match_parent,使用wrap_content时子view必须设置固定高度
  5. CollapsingToolbarLayout的子视图设置layout_collapseMode属性
  6. 关联悬浮视图设置app:layout_anchor,app:layout_anchorGravity属性

猜你喜欢

转载自blog.csdn.net/weixin_41805792/article/details/88813562