Material Design中的Snackbar

    今天我們討論一下另一個組件”Snackbar”.Snackbar是design support library中另一個組件,使用Snackbar我們可以在屏幕底部(大多時候)快速彈出消息,它和Toast非常相似,但是它更靈活一些。首先,來看一下這個官方的介紹。http://www.google.com/design/spec/components/snackbars-toasts.html#

  一    Snackbar的基本特徵

        1.比toast更加好,畢竟snackbar 可以響應點擊事件

        2.snackbar 同一時間有且只有一個在顯示。

       3.snackbar 上不要有圖標

       4.snackbar上action 只能有一個。

      5.如果有懸浮按鈕 floating action button的話,snackbar 在彈出的時候 不要覆蓋這個button.

      6.此外我個人認爲snackbar 在一定程度上可以替代dialog的某些應用場景。比如以前網絡不通的情況下 我們登陸失敗,會給一個dialog提示,現在就可以用snackbar 來做這個有action的提示 更加方便快捷。

二    Snackbar的基本使用
    Snackbar使用的時候需要一個控件容器用來容納Snackbar.官方推薦使用CoordinatorLayout這個另一個Android Support Design Library庫支持的控件容納。因爲使用這個控件,可以保證Snackbar可以讓用戶通過向右滑動退出。 Activity中獲取CoordinateorLayout作爲容器,然後調用Snackbar.make(Container, “SnackbarTest”, Snackbar.LENGTH_LONG).show();就可以生成一個Snackbar了

三   Snackbar簡單的例子

佈局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="android.com.snackbar.MainActivity">

    <Button
        android:id="@+id/btId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="點擊彈出snackBar"/>
    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        >
    </android.support.design.widget.CoordinatorLayout>

</RelativeLayout>

MainActivity代碼

  

package android.com.snackbar;

import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import static android.com.snackbar.R.layout.activity_main;

public class MainActivity extends AppCompatActivity {

    private CoordinatorLayout container;
    private Button mButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(activity_main);
        container= (CoordinatorLayout) findViewById(R.id.container);
        mButton= (Button) findViewById(R.id.btId);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
              Snackbar.make(container,"測試snackbar",Snackbar.LENGTH_LONG).show();

            }
        });
    }
}

效果如下


由於Snackbar是支持添加一個按鈕的,因此Snackbar的構造語句可以寫成這樣:

    

                Snackbar.make(container,"測試snackbar",Snackbar.LENGTH_LONG).setAction("測試", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Snackbar.make(container,"點擊action",Snackbar.LENGTH_LONG).show();
                    }
                }).show();

效果如下:

 

你要改變這個snackbar的背景色也是可以的 只需要

Snackbar sb=Snackbar.make(layout, "connection error", Snackbar.LENGTH_LONG).setAction("retry", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                    }
                });
                //紅色
                sb.getView().setBackgroundColor(0xfff44336);
                sb.show();
四    Snackbar 的源碼

      

/這個地方就是構造函數
    Snackbar(ViewGroup parent) {
        this.mParent = parent;
        this.mContext = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(this.mContext);
        this.mView = (Snackbar.SnackbarLayout)inflater.inflate(layout.layout_snackbar, this.mParent, false);
    }

    //這個地方就是我們調用的make函數 也就是整個類的一個入口 在這裏可以看到 我們的代碼轉入了snackbar的構造函數
    public static Snackbar make(View view, CharSequence text, int duration) {
        //注意看這個地方調用了 findsuitableparent這個函數
        Snackbar snackbar = new Snackbar(findSuitableParent(view));
        snackbar.setText(text);
        snackbar.setDuration(duration);
        return snackbar;
    }

    public static Snackbar make(View view, int resId, int duration) {
        return make(view, view.getResources().getText(resId), duration);
    }

    //這個函數其實作用就是無論你傳進去的是什麼view 我最終都會遍歷到framlayout爲止,因爲activity的最外層實際上就是一個framlayout
    //所以你在調用make函數的時候無論傳什麼值進去 snackabr都會從最底部彈出來 就是因爲這個函數做了這樣的工作 但是!!!!
                //如果在遍歷到最頂部的framlayout之前 遇到了一個framelayout 那麼就會從這個framlayout的底部彈出,而不會從屏幕的最下方彈出了。
    //這個地方CoordinatorLayout的優先級比framlayout還要高 所以你如果穿進去的view是CoordinatorLayout的話 這個snackbar 就一定會從
    //CoordinatorLayout 底部彈出了。如果你CoordinatorLayout的最底部恰好在屏幕中間 那麼snackbar 就會從屏幕中間彈出  而不會從底部彈出 這一點一定要注意
    @Nullable
    private static ViewGroup findSuitableParent(View view) {
        ViewGroup fallback = null;

        do {
            if(view instanceof CoordinatorLayout) {
                return (ViewGroup)view;
            }

            if(view instanceof FrameLayout) {
                if(view.getId() == 16908290) {
                    return (ViewGroup)view;
                }

                fallback = (ViewGroup)view;
            }

            if(view != null) {
                ViewParent parent = view.getParent();
                view = parent instanceof View?(View)parent:null;
            }
        } while(view != null);

        return fallback;
    }

轉自:http://www.open-open.com/lib/view/open1437460246974.html


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