Android Snackbar使用方法及小技巧-design

Snackbar和Toast相似,都是爲了給用戶提供交互信息,Snackbar是固定在底部的,顯示時從下往上滑出

這裏寫圖片描述

要使用Snackbar,需要在項目的build.gradle中添加依賴

dependencies {
     compile 'com.android.support:design:23.4.0'
}

Snackbar的使用方法和Toast很相似

Snackbar.make(mOpenTv, "消息內容", Snackbar.LENGTH_SHORT)
                        .setAction("確定", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {

                            }
                        })
                        .show();

第一個參數需要傳入一個View,可以是界面當中的任意一個View控件,Snackbar會自動根據這個控件找到最外層的佈局來顯示

第二個參數就是我們需要顯示的內容,注意這裏的內容最多顯示兩行哦,超出兩行後的內容會變成“…”

第三個參數爲Snackbar顯示的時長,有三種模式供選擇

  • LENGTH_SHORT:短時間顯示

  • LENGTH_LONG:長時間顯示

  • LENGTH_INDEFINITE:一直顯示,只有當用戶觸發Action點擊事件或手動刪除時纔會消失

Snackbar可以通過setAction方法設置一個點擊事件,和用戶進行交互

我們還可以通過setCallback方法來監聽Snackbar的顯示和關閉

        Snackbar sb = Snackbar.make(mOpenTv, "消息內容", Snackbar.LENGTH_SHORT);
        sb.setCallback(new Snackbar.Callback() {
            @Override
            public void onDismissed(Snackbar snackbar, int event) {
                super.onDismissed(snackbar, event);
                // Snackbar關閉時回調
            }

            @Override
            public void onShown(Snackbar snackbar) {
                super.onShown(snackbar);
                // Snackbar打開時回調
            }
        });
        sb.show();

Snackbar還支持滑出刪除,需要在佈局文件中使用CoordinatorLayout作爲根佈局
這裏寫圖片描述

建議要使用Snackbar的時候最好是以CoordinatorLayout作爲根佈局,如果以其它RelativeLayout,LinearLayout等作爲根佈局的話,會出現以下這種情況

這裏寫圖片描述

FloatingActionButton被遮到了,使用CoordinatorLayout作爲根佈局可以避免這種情況

這裏寫圖片描述

Snackbar只能在底部顯示嗎?
是也不是,爲啥這麼說呢,Snackbar確實是在CoordinatorLayout底部顯示的,但並不等於是在屏幕頂部
首先我們要知道Snackbar顯示的原理是什麼
之前介紹中的第一個傳進去的參數View,Snackbar會通過這個View控件找到它所在的根佈局,我們來查看下源碼

    public static Snackbar make(@NonNull View view, @NonNull CharSequence text,
            @Duration int duration) {
        Snackbar snackbar = new Snackbar(findSuitableParent(view));
        snackbar.setText(text);
        snackbar.setDuration(duration);
        return snackbar;
    }

我們傳進去的view會經過findSuitableParent方法的處理,我們再來看下這個方法的具體實現

    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;
    }

詳細的過程google的工程師已經寫的非常的清楚了,我們主要需要了解的就是當一個View的直接父佈局爲CoordinatorLayout時,就以這個CoordinatorLayout爲標準來顯示Snackbar
我們可以做個小實驗驗證一下
在傳入的View控件外面套一層CoordinatorLayout

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="100dp">

        <TextView
            android:id="@+id/tv_open_snackbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="打開Snackbar"
            android:textSize="28sp"/>
    </android.support.design.widget.CoordinatorLayout>

再運行一下看看,效果就變成了下面這樣
這裏寫圖片描述
所以說Snackbar的顯示位置還是可以通過這個小技巧來改變的

如果嫌默認的Snackbar太醜怎麼辦?
我們可以來自定義它的外觀

1.改變按鈕的文字顏色
通過調用setActionTextColor方法即可改變按鈕的文字顏色

        Snackbar sb = Snackbar.make(mOpenTv, "消息內容", Snackbar.LENGTH_SHORT);
        sb.setAction("確定", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });
        sb.setActionTextColor(Color.YELLOW);
        sb.show();

這裏寫圖片描述

2.改變消息內容的文字顏色
Snackbar沒有給我們提供改變消息文本顏色的api接口,但在查看源碼時發現了這個方法getView

    /**
     * Returns the {@link Snackbar}'s view.
     */
    @NonNull
    public View getView() {
        return mView;
    }

這裏返回的mView其實是一個SnackbarLayout佈局,在SnackbarLayout的構造方法中找到了它的佈局文件design_layout_snackbar_include

            // Now inflate our content. We need to do this manually rather than using an <include>
            // in the layout since older versions of the Android do not inflate includes with
            // the correct Context.
            LayoutInflater.from(context).inflate(R.layout.design_layout_snackbar_include, this);

design_layout_snackbar_include佈局文件裏只有兩個控件,一個TextView,一個Button

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
            android:id="@+id/snackbar_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:paddingTop="@dimen/design_snackbar_padding_vertical"
            android:paddingBottom="@dimen/design_snackbar_padding_vertical"
            android:paddingLeft="@dimen/design_snackbar_padding_horizontal"
            android:paddingRight="@dimen/design_snackbar_padding_horizontal"
            android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"
            android:maxLines="@integer/design_snackbar_text_max_lines"
            android:layout_gravity="center_vertical|left|start"
            android:ellipsize="end"
            android:textAlignment="viewStart"/>

    <Button
            android:id="@+id/snackbar_action"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/design_snackbar_extra_spacing_horizontal"
            android:layout_marginStart="@dimen/design_snackbar_extra_spacing_horizontal"
            android:layout_gravity="center_vertical|right|end"
            android:paddingTop="@dimen/design_snackbar_padding_vertical"
            android:paddingBottom="@dimen/design_snackbar_padding_vertical"
            android:paddingLeft="@dimen/design_snackbar_padding_horizontal"
            android:paddingRight="@dimen/design_snackbar_padding_horizontal"
            android:visibility="gone"
            android:textColor="?attr/colorAccent"
            style="?attr/borderlessButtonStyle"/>

</merge>

相信看到這裏大家應該知道怎麼做了,TextView的id爲snackbar_text,我們通過getView()來獲取這個TextView控件

        Snackbar sb = Snackbar.make(mOpenTv, "消息內容", Snackbar.LENGTH_SHORT);
        sb.setAction("確定", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });
        sb.setActionTextColor(Color.YELLOW);

        View view = sb.getView();
        TextView tv = (TextView) view.findViewById(R.id.snackbar_text);
        tv.setTextColor(Color.RED);

        sb.show();

這裏寫圖片描述
同樣的,我們也可以通過tv.setTextSize設置它的文字大小

3.改變消息內容的背景
同理,根據以上方法,得到它的佈局,調用對應的api接口就好

        View view = sb.getView();
        view.setBackgroundColor(Color.RED);

像這種紅紅的給用戶警告的提示,是不是比Toast要來的炫酷多了呢
這裏寫圖片描述

這裏寫圖片描述

4.給消息內容添加圖標
獲取到消息內容的TextView後,調用setCompoundDrawables方法設置它的圖標,可自由選擇圖標放置的位置,四個參數分別對應TextView的左、上、右、下

        Snackbar sb = Snackbar.make(mOpenTv, "消息內容", Snackbar.LENGTH_SHORT);
        sb.setAction("確定", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });
        sb.setActionTextColor(Color.YELLOW);

        View view = sb.getView();
        TextView tv = (TextView) view.findViewById(R.id.snackbar_text);
        Drawable d = ContextCompat.getDrawable(this, R.drawable.warn);
        d.setBounds(0, 0, d.getMinimumWidth(), d.getMinimumHeight());
        tv.setCompoundDrawables(d, null, null, null);   // 給TextView左邊添加圖標
        tv.setGravity(Gravity.CENTER);  // 讓文字居中

        sb.show();
    }

這裏寫圖片描述
注意要設置setGravity使其居中,不然文字默認在上面不好看啊

就先介紹這麼多,其實只要拿到了它的佈局,接下來怎麼整就看各位的喜好啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章