簡介
Snackbar是design support library中另一個組件,在屏幕底部(大多時候)快速彈出消息,它和Toast非常相似,列出一些特點:
- Snackbar是一個輕量級的反饋操作,會在手機的屏幕底部展示一個簡要Message,在更大的屏幕上則顯示在左下角。
- 當它顯示一段時間后或用戶與屏幕交互時它會自動消失。能支持滑動消失。
- 顯示在所有屏幕其它元素之上(屏幕最頂層),并不是像Toast一樣覆蓋在屏幕上。所以有鍵盤的顯示的時候鍵盤會擋住Snackbar,這種情況要提前隱藏鍵盤。
- 同一時間只能顯示一個snackbar。避免了使用一般Toast時的多次toast相互堆疊的問題。
- 可以通過設置action實現點擊交互事件。
- 可以在Snackbar顯示或者消失的時候設置Callback進行某些處理。
- 官方推薦和CoordinatorLayout配合使用,使用該布局的優勢在于:
- 用戶可以滑動(右滑)消除掉Snackbar。
- 當Snackbar出現的時候,布局會移動一些UI元素,比如右下角的懸浮按鈕會自動上移。就是使用此布局可以自動適配FloatingActionButton。
使用
準備:添加版本庫依賴:在app的dependencies中添加:(其中23.1.0為當前庫版本號)
compile 'com.android.support:design:23.1.0'
開始使用:
- 系統默認普通樣式
Snackbar.make(view, text, Snackbar.LENGTH_LONG).setAction("Action", null).show();// 無事件
Snackbar.make(llRoot, "floatAction", Snackbar.LENGTH_SHORT).setAction("Action", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Action click", Toast.LENGTH_SHORT).show();
}}).show();
}
});// 綁定一個事件
- View:Snackbar依附的View,系統優先尋找CoordinatorLayout,找不到就用頂層decor view或者該View的第一個FrameLayout父布局。實際使用時如果沒有CoordinatorLayout那就用根布局的View好了。
- text:要顯示的文本,支持R資源引用
- Duration:顯示時長
- Snackbar.LENGTH_LONG
- Snackbar.LENGTH_SHORT
- Snackbar.LENGTH_INDEFINITE:一直顯示,直至下一次新的顯示或者該Snackbar被dismiss。
設置Action
setAction:第一個是交互按鈕的顯示文本,第二個是監聽事件。-
使用回調
private void showSnackbarCallback(View view) {
Snackbar snackbar = Snackbar.make(view, R.string.on_loading_text, Snackbar.LENGTH_LONG).setAction("cancel", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Cancel", Toast.LENGTH_SHORT).show();
}
}).setCallback(callback);
snackbar.show();
snackbar.getView().setBackgroundColor(getResources().getColor(R.color.colorPrimary));
snackbar.setActionTextColor(getResources().getColor(R.color.colorAccent));
}private Snackbar.Callback callback = new Snackbar.Callback() { @Override public void onDismissed(Snackbar snackbar, int event) { super.onDismissed(snackbar, event); switch (event) { case DISMISS_EVENT_SWIPE: toolbar.setTitle("DISMISS_EVENT_SWIPE"); break; case DISMISS_EVENT_ACTION: toolbar.setTitle("DISMISS_EVENT_ACTION"); break; case DISMISS_EVENT_TIMEOUT: toolbar.setTitle("DISMISS_EVENT_TIMEOUT"); break; case DISMISS_EVENT_MANUAL: toolbar.setTitle("DISMISS_EVENT_MANUAL"); break; case DISMISS_EVENT_CONSECUTIVE: toolbar.setTitle("DISMISS_EVENT_CONSECUTIVE"); break; } } @Override public void onShown(Snackbar snackbar) { super.onShown(snackbar); toolbar.setTitle("snackbar onShown"); } };
- onDismissed里監聽消失動作:
DISMISS_EVENT_SWIPE:滑動Snackbar使其消失
DISMISS_EVENT_ACTION:點擊Snackbar上定義的Action
DISMISS_EVENT_TIMEOUT:到了設置的Duration時間后,超時消失
DISMISS_EVENT_MANUAL:調用了dismiss()使其消失
DISMISS_EVENT_CONSECUTIVE:有下一個Snackbar需要顯示 - onShown:監聽顯示動作
修改背景色和文字顏色
// 修改背景色
snackbar.getView().setBackgroundColor(getResources().getColor(R.color.colorPrimary));
// 修改Action提示文字的顏色
snackbar.setActionTextColor(getResources().getColor(R.color.colorAccent));
// 修改Message顯示文本的顏色,利用系統布局中TextView的id
((TextView) snackbar.getView().findViewById(R.id.snackbar_text)).setTextColor(getResources().getColor(R.color.colorAccent));-
自定義布局和樣式:
谷歌的MaterialDesign設計規范里好像不太贊成自定義各種花哨的布局,中文版的規范可參照這里:
[Snackbar與Toast](http://wiki.jikexueyuan.com/project/material-design/components/snackbars-and-toasts.html)
但是如果需求就是這么任性,那就繼續向下看:
Snackbar自己使用的是一個繼承自LinearLayout的自定義布局SnackbarLayout,里面就只有水平排布的兩個控件,靠左的TextView和靠右的Button,分別對應Message和Action,如果要自定義,也只能將自定義的View塞進這個SnackbarLayout中。只演示一個最左側添加一個ImageView的例子,太復雜的會占用更多MessageText的顯示空間。private void showSnackbarCustom() { Snackbar snackbar = Snackbar.make(llRoot, "Custom", Snackbar.LENGTH_SHORT); addCustomViewToSnackbar(snackbar, R.layout.layout_custom_snackbar, 0); snackbar.show(); } public void addCustomViewToSnackbar(Snackbar snackbar, int layoutId, int index) { //獲取snackbar的View(其實就是SnackbarLayout) View snackbarView = snackbar.getView(); //將獲取的View轉換成SnackbarLayout Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) snackbarView; //加載布局文件新建View View customView = LayoutInflater.from(snackbarView.getContext()).inflate(layoutId, null); ImageView ivImg = (ImageView) customView.findViewById(R.id.iv_img); ivImg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(SnackAndToastActivity.this, "Custom image", Toast.LENGTH_LONG).show(); } }); //設置新建布局參數 LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout .LayoutParams.WRAP_CONTENT); //設置新建布局在Snackbar內垂直居中顯示 p.gravity = Gravity.CENTER_VERTICAL; //將新建布局添加進snackbarLayout相應位置 snackbarLayout.addView(customView, index, p); }
Demo地址:maoranbian/MTime
參考文章:
沒時間解釋了,快使用Snackbar!——Android Snackbar花式使用指南
BTW:Snackbar的源碼短小精煉,有動畫,有自定義布局,有事件攔截,感覺是個很好的適合學習基本功的源碼Demo,Google工程師寫的哦~~