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