一、AppBarLayout
AppBarLayout是继承自LinearLayout,默认是垂直方向,可以看成是一个垂直方向的线性布局,其作用是将APPBarLayout包裹的内容都作为AppBar,支持手势滑动。
AppBarLayout必须作为Toolbar的父布局容器,换句话就是说,使用AppBarLayout布局时,需要包裹Toolbar布局。
支持手势滑动时,需要和CoordinatorLayout配合使用。
二、CoordinatorLayout
CoordinatorLayout是一个为子视图之间相互协调手势效果的协调布局, 在不指定视图位置时,和FrameLayout一样,所有视图都位于在左上角。一般都是和AppBarLayout 、CollapsingToolbarLayout配合使用。
三、CollapsingToolbarLayout
CollapsingToolbarLayout一般作为AppBarLayout的子视图使用,当其包裹Toolbar时,提供了一个可以折叠的Toolbar,需要有折叠效果的组件还需设置 layout_collapseMode属性。是继承自FrameLayout布局,如果包裹的视图不指定位置,会和FrameLayout一样位于在左上角。
使用上面这些布局,都要导入Material Design依赖包,我使用的是Android Studio 3.0版本,导入包
implementation 'com.android.support:design:28.0.0-alpha1'
四、使用 CoordinatorLayout + RecyclerView + AppBarLayout +( Toolbar) 实现Toolbar可手势滑动
(1)自定义一个Toolbar布局toolbar_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="?actionBarSize"> <ImageView android:id="@+id/iv" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="10dp" android:src="@drawable/toolbar_pic" android:layout_centerVertical="true"/> <LinearLayout android:id="@+id/ll_title" android:layout_toRightOf="@+id/iv" android:layout_marginLeft="10dp" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="主标题" android:textSize="15sp" android:textColor="#000000" android:padding="5dp"/> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="副标题" android:textSize="13sp" android:textColor="#ece8e8" android:padding="5dp"/> </LinearLayout> <ImageView android:id="@+id/iv2" android:layout_toLeftOf="@+id/iv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_search" android:layout_centerVertical="true" android:layout_marginRight="10dp"/> <ImageView android:id="@+id/iv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_more" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_marginRight="10dp"/> </RelativeLayout>
(2)activity_app_bar_layout.xml
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SAppBarLayoutActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/appbarlayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" app:layout_scrollFlags="scroll|enterAlways"> <include layout="@layout/toolbar_layout"/> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="android.support.v7.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>
(3)RecyclerView的适配器
public class RVMyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context context; private List<String> list; public RVMyAdapter(Context context, List<String> list) { this.context = context; this.list = list; } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { TextView textView=new TextView(context); return new RecyclerView.ViewHolder(textView) {}; } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) { ((TextView)viewHolder.itemView).setText(list.get(i)); } @Override public int getItemCount() { return list.size(); } }
(4)AppBarLayoutActivity.java
public class AppBarLayoutActivity extends Activity { private Toolbar toolbar; private RecyclerView recyclerView; private List<String> list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sapp_bar_layout); //设置toolbart替代ActionBar toolbar=findViewById(R.id.toolbar); setSupportActionBar(toolbar); //设置recyclerView填充数据 recyclerView=findViewById(R.id.recyclerView); list=new ArrayList<>(); for (int i = 0; i < 1000; i++) { list.add(String.format(Locale.CHINA,"第%03d条数据",i)); } recyclerView.setAdapter(new RVMyAdapter(this,list)); } }
(5)运行界面
(6)效果实现说明:
为了使Toolbar可以手势滑动,首先,给Toolbar设置app:layout_scrollFlags="scroll | enterAlways"属性。其次,CoordinatorLayout布局下必须包裹一个可以滑动的布局,比如,可以是RecyclerView(经测试,ListView、ScrollView不支持) , 并且给这滑动组件设置属性app:layout_behavior="@string/appbar_scrolling_view_behavior"来告诉CoordinatorLayout,该组件是带有滑动行为的组件,然后CoordinatorLayout在接收到滑动时会通知AppBarLayout 中可滑动的Toolbar可以滑出屏幕了。
给想要实现手势滑动的组件设置的layout_scrollFlags属性有如下几种选项:
scroll: 所有想滚动出屏幕的view都需要设置这个值,没有设置这个值的view将被固定在屏幕顶部。enterAlways: 任意向下的滚动都会导致该view变为可见,启用快速“返回模式”。 enterAlwaysCollapsed: 当滚动视图到达顶部时view才扩大到完整高度。exitUntilCollapsed: 滚动退出屏幕,最后折叠在顶端。
(7)总结
为了使Toolbar有手势滑动的效果,必须做到下面几点:
1、CoordinatorLayout作为整个布局的父布局容器
2、Toolbar的父布局容器须为AppBarLayout,给Toolbar设置属性
app:layout_scrollFlags=" ",值为scroll|enterAlways表示滚动出屏幕|任意向下滑动就可见,值为scroll|enterAlwaysCollapsed表示滚动出屏幕|向下滑动顶端出现才可见
3、CoordinatorLayout需包裹一个滑动组件,比如RecyclerView,并给滑动组件设置属性:
app:layout_behavior="@string/appbar_scrolling_view_behavior"
(8)扩展一下,稍稍修改下activity_app_bar_layout.xml布局,在AppBarLayout中增加一个ImageView控件,其他地方不变
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SAppBarLayoutActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/appbarlayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <ImageView android:layout_width="80dp" android:layout_height="80dp" android:layout_gravity="center" android:paddingTop="10dp" android:src="@drawable/toolbar_pic" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" app:layout_scrollFlags="scroll|enterAlways"> <include layout="@layout/toolbar_layout"/> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="android.support.v7.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>
界面如下图所示,运行中我们可以发现,这种情况下,即使Toolbar设置了属性app:layout_scrollFlags="scroll | enterAlways",RecyclerView在滑动过程中Toolbar也没有出现滑动。如果将app:layout_scrollFlags="scroll | enterAlways"属性设置给AppBarLayout,Toolbar仍然没有滑动。如果将app:layout_scrollFlags="scroll | enterAlways"属性设置给刚添加的ImageView,ImageView却出现了滑动,向上滑动时Toolbar会固定在顶部位置。如果这种情况想要实现Toolbar也可滑动,怎么办?这个问题将会在下面给出解决。
五、使用 CoordinatorLayout + RecyclerView + AppBarLayout + (CollapsingToolbarLayout +( ToolBar) ) 实现可折叠的Toolbar
(1)CollapsingToolbarLayout的常用属性
app:contentScrim="@color/colorAccent" //设置被折叠到顶部固定时候的背景
app:layout_scrollFlags="scroll | exitUntilCollapsed" //设置滑动标志 scroll: 所有想滚动出屏幕的view都需要设置这个值,exitUntilCollapsed: 滚动退出屏幕,最后折叠在顶端。
app:layout_collapseParallaxMultiplier="0.2" //设置CollapsingToolbarLayout滑动时其子视图的视觉差
app:layout_collapseMode="parallax" // 设置子视图的折叠模式 “pin”:固定模式,在折叠的时候最后固定在顶端;“parallax”:视差模式,在折叠的时候会有个视差折叠的效果。
(2)自定义的toolbar_layout布局、代码文件、RecyclerView适配器文件与上面的一样,这里就不重复贴了,这里只贴一下布局文件。
(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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".AppBarLayoutActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/appbarlayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:contentScrim="@color/colorAccent" app:layout_collapseParallaxMultiplier="0.2" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:layout_collapseMode="parallax"> <ImageView android:layout_width="80dp" android:layout_height="200dp" android:layout_gravity="center" android:src="@drawable/toolbar_pic" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" android:layout_gravity="bottom"> <include layout="@layout/toolbar_layout"/> </android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="android.support.v7.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>
(5)运行界面
(6)注意:Toolbar的高度layout_height必须固定,不能是“wrap_content”,否则Toolbar不会滑动,也不会折叠。
(7)扩展:如果将CollapsingToolbarLayout的属性app:layout_scrollFlags=""设置为scroll | enterAlways,就会实现可滑动的ImageView+Toolbar,这刚好可以解决四(7)中的问题。
说了这么多,具体还是要自己动手去实练一遍才有感觉。