一、CoordinatorLayout簡介
CoordinatorLayout是Material Design 的重要元件,它作為父布局使用,可以協調(coordinate)其子布局,實作多種關聯滾動效果。本文代碼參考cheesesquare
二、基本結構
對cheesesquare中的布局代碼進行了一些修改,把幾種布局放到同一個界面上。
<?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"
android:fitsSystemWindows="true"
tools:context="com.quickframe.ui.MainDrawerActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
android:theme="@style/AppTheme.AppBarOverlay">
<android.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">
<ImageView
android:id="@+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"/>
<!--app:layout_scrollFlags="scroll|enterAlways|snap"-->
<android.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"/>
</android.support.design.widget.CollapsingToolbarLayout>
<android.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"/>
</android.support.design.widget.AppBarLayout>
<include
layout="@layout/content_main_drawer"
android:visibility="gone"/>
<android.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"/>
<android.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"/>
</android.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中,有一行代碼
這裡定義了滾動視圖與響應滾動視圖AppBarLayout之間的聯系。在定義了layout_behavior後,CoordinateLayout就會搜尋其子view,看是否有view和這下behavior相關聯。檢視appbar_scrolling_view_behavior的相關資訊,可以看到
<string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>
它其實是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隻有部分可見,就會自動滾動到最近的邊界,確定了滾動不會在中間狀态的時候停止。
實際情況如圖
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 == ) {
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、參考官方文檔, 在布局裡添加
<android.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<android.support.design.widget.TabItem
android:text="@string/tab_text"/>
<android.support.design.widget.TabItem
android:icon="@drawable/ic_android"/>
</android.support.design.widget.TabLayout>
如果想設定tab圖示的話,可以用
如果想設定tab的監聽,可以通過AddOnTabSelectedListener(OnTabSelectedListener)。
六、FloatingActionButton
基本屬性:
app:backgroundTint=”@color/grey” 背景顔色
* app:rippleColor=”#33728dff”* 點選的背景色
app:elevation=”2dp” 正常陰影大小
app:pressedTranslationZ=”4dp” 按下時的陰影大小
app:fabSize=”normal” 可選的有auto, normal和mini
關于FAB滑動隐藏和彈出子菜單的,可以參考這篇部落格以及一個第三方庫。