Material Design Patterns 教學 (3) - Snackbar & CoordinatorLayout
相信大家有用過 Toast
, Toast
是 Android App 用來顯示簡短提示或通知的一種方法。Material Design 引入 Snackbar
,用來取代 Toast
。比起 Toast
,Snackbar
歸屬於顯示中的 view
,可以加「行動」按鍵,並且可以以左去右形式掃走。
Snackbar 用法
Snackbar 使用方法是跟 Toast
一樣:
Snackbar.make(contentView, "I am snackbar", Snackbar.LENGTH_SHORT).show();
跟 Toast
不同的是,Snackbar
是以 view
作參數,而不是以 context
。這確保 Snackbar
只在有 view
顯示時才出現,不會跟 Toast
般被濫用,在背景 Service
中執行 toast.show()
,引致用戶跟本不知是那個 app 在顯示通知的問題。
要加「行動」按鍵的話可以用 setAction()
Snackbar.make(contentView, "I am snackbar", Snackbar.LENGTH_SHORT)
.setAction("Undo", new View.OnClickListener() {
@Override
public void onClick(View v) {
// action triggered
}
})
.show();
但有沒有發覺 Snackbar
會擋著 FAB ?
移動吧!FAB
這時便要使用 Design Support Library 另一猛將: CoordinatorLayout
。
CoordinatorLayout
是一個 FrameLayout
的強化版。透過定義 Behavior
,它能協調自身各 child view
間的互動。由於 Google 的 FAB 已內建支援 CoordinatorLayout
,我們只需將包著 contentView
的 FrameLayout
改為 android.support.design.widget.CoordinatorLayout
便可解決問題。
現在 Snackbar
出現時 FAB 會跟著動了。
簡單吧?但若你選用之前介紹的 open source FAB 便沒有效果。
為其他 FAB library 加上 Behavior
要自行加上其實也不難。首先新建一個 class,要 extend Behavior
:
public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionButton>
{
}
因為要在 xml
中使用,所以需新增以下 constructor:
public FloatingActionButtonBehavior(Context context, AttributeSet attributeSet){}
我們需要使用當中兩個 methods:layoutDependsOn()
和 onDependentViewChanged()
。看看 document 便知它們的用處。
layoutDependsOn(CoordinatorLayout parent, V child, View dependency)
Determine whether the supplied child view has another specific sibling view as a layout dependency.
onDependentViewChanged(CoordinatorLayout parent, V child, View dependency)
Respond to a change in a child's dependent view
This method is called whenever a dependent view changes in size or position outside of the standard layout flow.
先 override layoutDependsOn()
。因我們想留意 Snackbar
的動向,所以當 dependency
是 SnackBarLayout
的話便 return true
;
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
return dependency instanceof Snackbar.SnackbarLayout;
}
而 onDependentViewChanged()
是實際控制 FAB 移動的 method。我們想 FAB 跟隨 Snackbar
向上移動,所以用 setTranslationY()
:
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
child.setTranslationY(translationY);
return true;
}
這樣 FloatingActionButtonBehavior
便完成。
最後在 FAB 加上 app:layout_behavior
即可
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="8dp"
android:layout_marginRight="8dp"
android:src="@drawable/ic_add_circle_outline_white"
app:layout_behavior="com.thirtysparks.tutorial.designlib.FloatingActionButtonBehavior"
/>
結語
Snackbar
為新的 Toast
,建議大家在 Material Design 中儘量不要再用 Toast
了。CoordinatorLayout
則可方便地控制各元件間的互動行為。下次我們會看看如何使用 CoordinatorLayout
來隱藏和顯示Toolbar
。
https://github.com/goofyz/android-material-design-tutorial/tree/part3_snackbar_coordinatorlayout