這篇文章中,介紹到的其它元件有TextInputLayout,FloatingActionButton,Snackbar,CoordinatorLayout。
該專題的其它文章:
『Material Design入門學習筆記』前言
『Material Design入門學習筆記』動畫(含demo)
『Material Design 入門學習筆記』主題與 AppCompatActivity(附 demo)
『Material Design入門學習筆記』RecyclerView與CardView(附demo)
demo下載
元件介紹
CoordinatorLayout
這一篇講的元件有些多,所以要從頭說起,頭是哪呢?就是佈局檔案,佈局檔案的頭是哪呢?就是CoordinatorLayout。
CoordinatorLayout被譽為超級FrameLayout。
主要是實現兩個功能:
- 作為頂層佈局
- 排程協調子佈局
比如說,接下來會講到的Snackbar,就只有依靠CoordinatorLayout才能實現一些特殊操作,這個後面會講到。
CoordinatorLayout功能強大,主要是依靠一個Behavior物件。CoordinatorLayout自己並不控制View,所有的控制權都在Behavior。
這個Behavior可以通過自定義的方式來實現自己的邏輯。寫到這裡,我突然發現後面沒法介紹了,因為介紹Behavior的功能需要依賴其它元件,那就放在後面再介紹Behavior吧。
這裡強調一下,接下來介紹的所有元件,都會用到這個庫:compile 'com.android.support:design:22.2.1'複製程式碼
AppBarLayout
AppBarLayout繼承自LinearLayout,佈局方向為垂直方向。但是它內部封裝了一些手勢變換的動畫。
首先它需要依賴CoordinatorLayout作為父容器,同時也要求一個具有可以獨立滾動的子View。
他的子View會有一個設定引數app:layout_scrollFlags
有一下幾種設定: scroll
:設為scroll的View會跟隨滾動事件一起發生移動, 所有想滾動出螢幕的view都需要設定這個flag,沒有設定這個flag的view將被固定在螢幕頂部。enterAlways
:設為enterAlways的View,當ScrollView往下滾動時,該View會直接往下滾動,而不用考慮ScrollView是否在滾動,這個flag讓任意向下的滾動都會導致該view變為可見,如啟用快速“返回模式”。exitUntilCollapsed
:值設為exitUntilCollapsed的View,當這個View要往上逐漸“消逝”時,會一直往上滑動,直到剩下的的高度達到它的最小高度後,再響應ScrollView的內部滑動事件。簡而言之,滾動退出螢幕,最後摺疊在頂端。enterAlwaysCollapsed
:是enterAlways的附加選項,一般跟enterAlways一起使用,它是指,View在往下“出現”的時候,首先是enterAlways效果,當View的高度達到最小高度時(注意你的view需要設定minHeight屬性),View就暫時不去往下滾動,直到ScrollView滑動到頂部不再滑動時,View再繼續往下滑動,直到滑到View的頂部結束。
需要注意的是,後面兩種模式基本只有在CollapsingToolbarLayout才有用。CollapsingToolbarLayout
CollapsingToolbarLayout繼承自FrameLayout,作用是為Toolbar提供了摺疊功能。
下面介紹一些引數:app:contentScrim
這個引數可以讓CollapsingToolbarLayout在收縮的時候,背景圖片消失的時候,指定一個顏色。app:collapsedTitleGravity
指定摺疊狀態的標題如何放置,可選值:top、bottom等app:collapsedTitleTextAppearance
指定摺疊狀態標題文字的樣貌app:expandedTitleTextAppearance
指定展開狀態標題文字的樣貌app:expandedTitleGravity
展開狀態的標題如何放置app:titleEnabled
指定是否顯示標題文字app:toolbarId
指定與之關聯的ToolBar,如果未指定則預設使用第一個被發現的ToolBar子Viewapp:expandedTitleMarginStart
指定展開狀態標題距離開始位置的高度app:expandedTitleMarginBottom
指定展開狀態標題距離底部的距離app:expandedTitleMarginEnd
指定展開狀態標題距離結束位置的高度app:layout_collapseParallaxMultiplier
="0.7"設定視差的係數,介於0.0-1.0之間。app:layout_collapseMode
“pin”:固定模式,在摺疊的時候最後固定在頂端;“parallax”:視差模式,在摺疊的時候會有個視差摺疊的效果。app:layout_anchor``app:layout_anchorGravity
兩個屬性連同一起,與某一個AppBarLayout控制元件相關聯,確定位置。TextInputLayout
TextInputLayout控制元件和LinearLayout完全一樣,它只是一個容器。跟ScrollView一樣,TextInputLayout只接受一個子元素。子元素需要是一個EditText元素。
EditText中有一個引數hint,這個大家都不陌生,但是如果EditText放在TextInputLayout中,則會讓hint變成一個在EditText上方的浮動標籤,同時還包括一個material動畫。FloatingActionButton
FloatingActionButton是一個圓形的按鈕,跟Button一樣會有點選事件。不同的是,可以設定陰影,可以設定反饋動畫。而且如果你設定的背景圖片是一個方形的,會在圓形按鈕中間顯示。佈局檔案
上面介紹了一些基本屬性,現在看一下整體的佈局檔案
<?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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="256dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
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="@drawable/logo"
app:layout_collapseMode="parallax"
/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/inputwrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<EditText
android:id="@+id/input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="輸入內容"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
android:src="@mipmap/ic_launcher"
android:id="@+id/btn_ok"
/>
</android.support.design.widget.CoordinatorLayout>複製程式碼
在該佈局檔案中使用了Toolbar,關於它的相關屬性,可以參考我之前的文章,這裡不再重複介紹。
TextInputLayout有人會問為什麼TextInputLayout使用app:layout_behavior="@string/appbar_scrolling_view_behavior"
,其實為了適配好位置,最好在外面加一層NestedScrollView,因為涉及到滑動嘛,但是這裡暫時不用,因為那是下一篇文章的內容。
程式碼
下面貼出相關的程式碼:
public class CollapsingActivity extends AppCompatActivity {
private FloatingActionButton okBtn;
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collapsing);
initToolBar();
TextInputLayout inputWrapper = (TextInputLayout) findViewById(R.id.inputwrapper);
editText = (EditText)findViewById(R.id.input);
okBtn = (FloatingActionButton)findViewById(R.id.btn_ok);
okBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
hideKeyboard();
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.main_content),editText.getText().toString(),Snackbar.LENGTH_SHORT);
mySnackbar.setAction(editText.getText().toString(), new OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(CollapsingActivity.this,"click Snackbar",Toast.LENGTH_LONG).show();
}
});
mySnackbar.show();
}
});
okBtn.setCompatElevation(0);
inputWrapper.setHintAnimationEnabled(true);
inputWrapper.setHint("請輸入內容");
}
private void hideKeyboard() {
View view = getCurrentFocus();
if (view != null) {
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).
hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
private void initToolBar(){
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setTitle("CollapsingActivity");//設定標題
toolbar.setNavigationIcon(R.mipmap.ic_launcher_round);//設定返回鍵,我這裡沒有,就有icon代替吧
toolbar.setNavigationOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});//返回監聽
toolbar.setSubtitle("by deep");//設定副標題
}
}複製程式碼
簡單說一下程式碼的邏輯,在介面上有個輸入框,輸入內容,點選FloatingActionButton,會將內容做一個Snackbar的展示,這是在底部會有一個Snackbar,Snackbar可以通過setAction
方法設定點選事件,它的第一個引數是按鈕顯示的文字,第二個引數是點選事件,我這裡是點選Snackbar會再彈出一個Toast。
關於Snackbar的初始化,可以使用make
方法,這裡需要注意它的引數:
- 第一個引數是一個view,我試過,可以設定介面任何一個View,但是最好設定為父容器CoordinatorLayout,這樣的話,會有一個滑動消除的手勢。
- 第二個引數是顯示的內容,第三個引數是顯示時長。
自定義behavior
在上文中提到過CoordinatorLayout功能如此強大,全依賴於Behavior物件。
我們先看一下原始碼,Behavior是一個抽象類,public static abstract class Behavior<V extends View>
,我們可以根據View隨意去實現。
原始碼中的實現這個抽象類的有以下幾個:
- AppBarLayout.Behavior;
- AppBarLayout.ScrollingViewBehavior;
- FloatingActionButton.Behavior;
- Snackbar.Behavior;
- BottomSheetBehaviro;
- SwipeDismissBehavior;
- HeaderBehavior;
- ViewOffsetBehavior;
- HeaderScrollingViewBehavior;
其中也有抽象類。
上面我們用到的就有ScrollingViewBehavior和FloatingActionButton.Behavior,由於FloatingActionButton.Behavior預設就是設定好的,所以我們沒有在佈局檔案中寫。
那麼我們現在可以重新寫一個FloatingActionButton的Behavior。
在寫之前最好去讀一下Behavior這個抽象類,其中很多概念和關聯需要弄明白。
其中重要的兩個概念
- child 它是一個View, 是該Behavior的關聯物件,也即Behavior所要操作的物件
- dependency ,也是個View,是 child的依賴物件,同時也是Behavior對child進行操作的根據
例如我們上面那個佈局檔案中child就是FloatingActionButton,dependency就是AppBarLayout。
還有一些方法:layoutDependsOn
用來確定依賴關係,原文是:Determine whether the supplied child view has another specific sibling view as a layout dependency.
意思是,這個view有沒有兄弟view。
onDependentViewChanged
Respond to a change in a child's dependent view
當我們的 dependency 發生改變的時候,這個方法會呼叫,而我們在 onDependentViewChanged 方法里根據需求做相應的介面處理即可。
我們簡單寫一個FloatingActionButton跟隨AppBarLayout移動的例子:
```
public class CustomBehavior extends CoordinatorLayout.Behavior{
public CustomBehavior() {
}
public CustomBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
return dependency instanceof AppBarLayout;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
float translationY = Math.abs(dependency.getTop());
Log.e("xxxxxx ","translationY="+translationY);
child.setY(800-translationY);
return true;
}複製程式碼
}
然後設定到佈局檔案的對應位置:複製程式碼
```
自定義Behavior的方式就介紹到這。
總結
本來想在文章中插圖,但是由於動圖過大,上傳總是失敗,所以,還是請感興趣的朋友執行demo看一下效果即可。後面的文章還是對本文的延伸,增添了一些新的元件,敬請關注。
有問題可以給我留言,或者關注我的公眾號留言。