Material Design 控件知識梳理(1) - Android Design Support Library 是什麼 Material Design 控件知識梳理(2) - AppBarLayout & CollapsingToolbarLayout Material Design 控件知識梳理(3) - BottomSheet && BottomSheetDialog && BottomSheetDialogFragment Material Design 控件知識梳理(4) - FloatingActionButton Material Design 控件知識梳理(5) - DrawerLayout && NavigationView Material Design 控件知識梳理(6) - Snackbar Material Design 控件知識梳理(7) - BottomNavigationBar Material Design 控件知識梳理(8) - TabLayout Material Design 控件知識梳理(9) - TextInputLayoutandroid
Snackbar
的做用和以前使用的Toast
相似,都是做爲一種輕量級的用戶提示: bash
Toast
相比,它又增長了一些額外的交互操做,今天咱們就一塊兒來學習一下有關
Snackbar
的知識。
Snackbar
的基礎使用當咱們須要使用Snackbar
時,首先須要調用它的make
靜態方法來得到一個Snackbar
對象,以後咱們對於Snackbar
的操做都是經過這個對象:ide
public void showSnackBar(View view) {
mSnackBarRootView = Snackbar.make(mCoordinatorLayout, "MessageView", Snackbar.LENGTH_INDEFINITE);
mSnackBarRootView.setActionTextColor(getResources().getColor(android.R.color.holo_orange_dark));
mSnackBarRootView.setAction("ActionView", new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("mSnackBarRootView", "click ActionView");
}
});
mSnackBarRootView.show();
}
複製代碼
對於Snackbar
,能夠分爲兩個區域,MessageView
和ActionView
,其中MessageView
只支持設置文案,而ActionView
不只支持設置文案,還支持設置文案的顏色以及監聽點擊事件,具體的方法你們能夠查閱API
: 函數
Snackbar
時,須要像上面同樣主動調用show()
方法。Snackbar
時,有如下幾種操做方式:dismiss
方法ActionView
Snackbar
setDuration
方法,讓Snackbar
在通過指定的時間以後自動隱藏Snackbar
進階Snackbar
的外觀從上面能夠看出,Snackbar
對於外觀的支持不夠充分,好比不能定義MessageView
的顏色、以及整個Snackbar
的背景等等,下面,咱們就來看一下如何對它的外觀進行進一步的定製。 源碼當中對Snackbar
對象的初始化分爲了下面三步操做:oop
public static Snackbar make(@NonNull View view, @NonNull CharSequence text,
@Duration int duration) {
//1.尋找Snackbar的父容器
final ViewGroup parent = findSuitableParent(view);
if (parent == null) {
throw new IllegalArgumentException("No suitable parent found from the given view. "
+ "Please provide a valid view.");
}
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
//2.實例化出Snackbar的佈局
final SnackbarContentLayout content =
(SnackbarContentLayout) inflater.inflate(
R.layout.design_layout_snackbar_include, parent, false);
//3.利用父容器和Snackbar的佈局,構造Snackbar對象
final Snackbar snackbar = new Snackbar(parent, content, content);
snackbar.setText(text);
snackbar.setDuration(duration);
return snackbar;
}
複製代碼
經過查看佈局,能夠發現SnackbarContentLayout
就是包含了MessageView
和ActionView
的父容器,也就是例子當中的黑色背景: 佈局
SnackbarContentLayout
呢,咱們看一下
Snackbar
的構造函數:
protected BaseTransientBottomBar(@NonNull ViewGroup parent,
@NonNull View content,
@NonNull ContentViewCallback contentViewCallback) {
//這個是咱們傳入的mCoordinatorLayout.
mTargetParent = parent;
//mView是mCoordinatorLayout的子View,同時又是SnackbarContentLayout的父容器
mView = (SnackbarBaseLayout) inflater.inflate(
R.layout.design_layout_snackbar, mTargetParent, false);
mView.addView(content);
}
複製代碼
而Snackbar
提供了getView
方法來獲得mView
對象,也就是佈局中的Snackbar$SnackbarLayout
:學習
public View getView() {
return mView;
}
複製代碼
那麼整個邏輯就很清楚了,咱們能夠經過經過mView
得到SnackbarContentLayout
,而後進行一系列的定製:字體
Snackbar
的背景:
private void changeSnackBarBackgroundColor(Snackbar snackbar) {
View view = snackbar.getView();
view.setBackgroundColor(getResources().getColor(android.R.color.holo_purple));
}
複製代碼
MessageView
字體的顏色和大小:
private void changeSnackBarMessageViewTextColor(Snackbar snackbar) {
ViewGroup viewGroup = (ViewGroup) snackbar.getView();
SnackbarContentLayout contentLayout = (SnackbarContentLayout) viewGroup.getChildAt(0);
TextView textView = (TextView) contentLayout.getChildAt(0);
textView.setTextColor(getResources().getColor(android.R.color.darker_gray));
}
複製代碼
Snackbar
彈出位置分析Snackbar
會彈出在父容器的底部,也就是上面findSuitableParent
的過程,咱們來分析一下這一尋找的過程,就能夠知道Snackbar
彈出的位置:ui
private static ViewGroup findSuitableParent(View view) {
ViewGroup fallback = null;
do {
if (view instanceof CoordinatorLayout) {
// We've found a CoordinatorLayout, use it return (ViewGroup) view; } else if (view instanceof FrameLayout) { if (view.getId() == android.R.id.content) { // If we've hit the decor content view, then we didn't find a CoL in the // hierarchy, so use it. return (ViewGroup) view; } else { // It's not the content view but we'll use it as our fallback fallback = (ViewGroup) view; } } if (view != null) { // Else, we will loop and crawl up the view hierarchy and try to find a parent final ViewParent parent = view.getParent(); view = parent instanceof View ? (View) parent : null; } } while (view != null); // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback return fallback; } 複製代碼
它實際上是從咱們在make
方法中傳入的View
做爲起點,沿着整個View
樹向上尋找,若是發現是CoordinatorLayout
或者到達了R.id.content
,那麼就中止尋找,不然將一直到達View
樹的根節點爲止,因此,若是咱們的CoordinatorLayout
不是全屏的話,那麼Snackbar
有可能不是彈出在整個屏幕的底部,例以下面這樣,咱們給Snackbar
添加了一個marginBottom
:spa
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="200dp"
tools:context="com.demo.lizejun.repotransition.SnackBarActivity">
<TextView
android:id="@+id/show_snack_bar"
android:text="showSnackBar"
android:layout_width="match_parent"
android:layout_height="66dp"
android:gravity="center"
android:layout_margin="5dp"
android:textColor="@android:color/white"
android:background="@android:color/holo_orange_dark"
android:onClick="showSnackBar"/>
</android.support.design.widget.CoordinatorLayout>
複製代碼
那麼彈出的效果爲:
Snackbar
和FloatingActionButton
的結合當Snackbar
彈出的時候,有可能會遮擋底部的FloatingActionButton
,此時就須要在make
方法中傳入CoordinatorLayout
,讓Snackbar
彈出的時候,讓Fab
上移必定的高度,能夠參考以前的這篇文章:MD控件 - FloatingActionButton
Snackbar
使用起來很簡單,它比Toast
增長了更多的操做性,也是官方推薦的替換Toast
的控件。