一、CoordinatorLayout简介
CoordinatorLayout是Material Design 的重要组件,它作为父布局使用,可以协调(coordinate)其子布局,实现多种联动滚动效果。本文代码参考cheesesquare
二、基本结构
对cheesesquare中的布局代码进行了一些修改,把几种布局放到同一个界面上。
"1.0" encoding="utf-8"?>
.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"
android:fitsSystemWindows="true"
tools:context="com.quickframe.ui.MainDrawerActivity">
.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
android:theme="@style/AppTheme.AppBarOverlay">
.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="250dp"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed|snap"
android:minHeight="50dp"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
"@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
android:src="@mipmap/ori"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7"/>
.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
.support.design.widget.CollapsingToolbarLayout>
.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
app:tabMode="fixed"
app:tabIndicatorHeight="@dimen/indicator_height"
android:background="@color/white"
app:tabIndicatorColor="@color/black"
app:tabSelectedTextColor="@color/black"
app:tabTextColor="@color/grey"/>
.support.design.widget.AppBarLayout>
"@layout/content_main_drawer"
android:visibility="gone"/>
.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:backgroundTint="@color/grey"
app:rippleColor="#33728dff"
app:srcCompat="@android:drawable/ic_dialog_email"/>
.support.design.widget.CoordinatorLayout>
如果对布局代码感觉混乱或者初次接触CoordinateLayout的话,可以看下结构图
红框CoordinateLayout 父布局, 其中包含两部分:滚动视图和响应滚动视图
绿框ViewPager ViewPager也可换成其它布局如FrameLayout, 重点是此布局内必须有支持嵌套滚动的view, 如RecyclerView,NestedScrollView, 目前ListView不支持嵌套滚动。
蓝框AppBarLayout 响应滚动的容器布局, 当绿框中的视图滚动时,让AppBarLayout也产生滚动。可在其中写入多个子view,对每个子view定义各自的响应滚动属性,
紫框CollapsingToolbarLayout 作为AppBarLayout的子view之一,响应滚动,可折叠版的ToolBar, 可加入各种子控件如imageView, ToolBar等
灰框TabLayout AppBarLayout的子view之一, 配合ViewPager使用。
所以,CoordinateLayout主要包含了 滚动视图 和 响应滚动视图
三、滚动视图
在滚动视图ViewPager中,有一行代码
app:layout_behavior="@string/appbar_scrolling_view_behavior"
这里定义了滚动视图与响应滚动视图AppBarLayout之间的联系。在定义了layout_behavior后,CoordinateLayout就会搜索其子view,看是否有view和这下behavior相关联。查看appbar_scrolling_view_behavior的相关信息,可以看到
"appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior
它其实是AppBarLayout中的一个类ScrollingViewBehavior, 实现了滚动视图与AppBarLayout之间的联合滚动
也就是说,我们在滚动视图中通过layout_behavior定义一个行为behavior,作为滚动视图与响应滚动视图之间的联系,就可以实现各种联动效果,更进一步的话,可以自定义Behavior。
四、CollapsingToolbarLayout
AppBarLayout继承自LinearLayout,布局方式为垂直,在这里可以把它当成LinearLayout,只是它可以让它的子view实现响应滚动。在AppBarLayout里我们可以通过app:layout_scrollFlags 给它的子view设置动作属性, 上面的代码中,CollapsingToolbarLayout作为AppBarLayout的一个子view。
先来看下scrollFlags可以设置哪些动作,它的几个动作可以配合使用。
1. scroll: 子view如果想要滑出屏幕外,就必须设置这个flag,如果没有设置,那子view就只能停留在屏幕顶部。
2. enterAlways: 字面翻译 “总是进入”,子view设置了这个动作属性后,只要有任意的下滑动作,就可以让子view马上出现
3. enterAlwaysCollapsed: 字面意思是”总是折叠进入”,是enterAlways的扩展型,需要和enterAlways一起配合使用。这个属性一般要同时设置最小高度android:minHeight=”50dp”,也就是其折叠状态的高度,如果在CollapsingToolbarLayout里加了Toolbar同时设置了其高度的话,不用加上minHeight也可以实现这个属性动作的效果。当有下滑动作时,子view会以最小高度即折叠状态出现; 当继续下滑,直到滚动视图不能再滚动时,子view才会开始展开。
4. exitUntilCollapsed: 向上收缩视图,达到最小高度时,就会消失。当CollapsingToolbarLayout中有Toolbar时,可以使Toolbar保持在最顶部。
5. snap: 23.1.0的Desing Support Library新加了snap属性,在滚动结束时,如果view只有部分可见,就会自动滚动到最近的边界,确保了滚动不会在中间状态的时候停止。
实际情况如图
app:layout_scrollFlags="scroll|enterAlways|snap"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed|snap"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
CollapsingToolbarLayout是一种可折叠式的Toolbar,继承自FrameLayout,在其中可以加入Toolbar,ImageView等各种控件,给CollapsingToolbarLayout设置了layout_scrollFlags,它就可以对其中的控件的响应滚动事件进行控件,它可以设置的属性如下。
app:collapsedTitleGravity 折叠状态时标题的放置布局,可以设为top, bottom, right, left, center, fill_vertical, start等。
app:expandedTitleGravity 展开状态时标题的放置布局,设置同上。
app:collapsedTitleTextAppearance 折叠状态时标题的样式,可以通过style进行设置。
app:expandedTitleTextAppearance 展开状态时标题的样式。
app:contentScrim=”?attr/colorPrimaryDark” 折叠时的背景,当Toolbar保留在顶部时,可以通过该属性设置Toolbar的背景,
app:expandedTitleMarginStart
app:expandedTitleMargin
app:expandedTitleMarginBottom
app:expandedTitleMarginEnd 展开状态时标题的Margin
对于CollapsingToolbarLayout其中的控件,可以通过app:layout_collapseMode来设置折叠效果
app:layout_collapseMode=”parallax” 视觉差效果,一般配合app:layout_collapseParallaxMultiplier=”0.7”使用,视差系数为0.0~1.0。
app:layout_collapseMode=”pin” 固定模式,Toolbar设置为pin后,可以固定在顶部不被滑出。
判断CollapsingToolbarLayout的状态
可以通过继承AppBarLayout.OnOffsetChangedListener进行监听。
@Override
public void onOffsetChanged(AppBarLayout mAppBarLayout, int verticalOffset) {
if (verticalOffset == 0) {
if (mState != CollapsingToolbarLayoutState.EXPANDED) {
mState = CollapsingToolbarLayoutState.EXPANDED; // 修改状态为展开
Log.d("state", "展开");
}
} else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) {
if (mState != CollapsingToolbarLayoutState.COLLAPSED) {
mState = CollapsingToolbarLayoutState.COLLAPSED; // 修改状态为折叠
Log.d("state", "折叠");
}
} else {
if (mState != CollapsingToolbarLayoutState.INTERNEDIATE) {
mState = CollapsingToolbarLayoutState.INTERNEDIATE; // 修改状态为中间
Log.d("state", "中间");
}
}
}
private enum CollapsingToolbarLayoutState {
EXPANDED, COLLAPSED, INTERNEDIATE
}
五、TabLayout
TabLayout用于配合Viewpager使用,可以很简单的就实现TabPageIndicator的效果。
先看下一些基本属性:
app:tabIndicatorHeight=”@dimen/indicator_height” 指示条高度,想隐藏时可以直接设为0
android:background=”@color/white” TabLayout背景
app:tabIndicatorColor=”@color/black” 指示条颜色
app:tabSelectedTextColor=”@color/black” 选中时的字体颜色
app:tabTextColor=”@color/grey” 正常字体颜色
app:tabMode=”fixed” 模式设置, fixed表示每个tab固定不会动,scrollable表示可以滑动,当有多个时,当前选中tab会一直滑动保持在屏幕正中间,除非不能再滑动。
app:tabMinWidth=”50dp” tab的最小宽度
app:tabGravity=”fill” 可以设置fill或center,fill时tab均分填满,center时,当tab较少时,只挤在中间。
app:tabTextAppearance=”@style/TabLayoutTextStyle” 可以在style中设置字体样式,比如字体大小。
使用的话,有几种方式
1、直接绑定viewpager
mFragmentAdapter = new FragmentAdapter(getSupportFragmentManager());
mFragmentAdapter.addFragment(new RvListFragment(), "列表");
mFragmentAdapter.addFragment(new RvGridFragment(), "网格");
mFragmentAdapter.addFragment(new RvStagFragment(), "瀑布");
mFragmentAdapter.addFragment(new NestCardFragment(), "卡片");
viewPager.setAdapter(mFragmentAdapter);
// 将TabLayout与viewpager绑定
tabLayout.setupWithViewPager(viewPager);
这样子可以直接做出上面图片的效果,简单方便
2、addTab
tabLayout.addTab(tabLayout.newTab().setText("列表"));
tabLayout.addTab(tabLayout.newTab().setText("网格"));
或者定义后再添加
private TabLayout.Tab mTabOne;
3、参考官方文档, 在布局里添加
.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
.support.design.widget.TabItem
android:text="@string/tab_text"/>
.support.design.widget.TabItem
android:icon="@drawable/ic_android"/>
.support.design.widget.TabLayout>
如果想设置tab图标的话,可以用
tabLayout.getTabAt(0).setIcon();
如果想设置tab的监听,可以通过AddOnTabSelectedListener(OnTabSelectedListener)。
六、FloatingActionButton
基本属性:
app:backgroundTint=”@color/grey” 背景颜色
* app:rippleColor=”#33728dff”* 点击的背景色
app:elevation=”2dp” 正常阴影大小
app:pressedTranslationZ=”4dp” 按下时的阴影大小
app:fabSize=”normal” 可选的有auto, normal和mini
关于FAB滑动隐藏和弹出子菜单的,可以参考这篇博客以及一个第三方库。