1. 程式人生 > >Material Design學習之 Snackbars(詳細分析,Toast的加強版)

Material Design學習之 Snackbars(詳細分析,Toast的加強版)

這幾篇關於Material Design文章的程式碼幾乎都是Git上摘錄的,我做的事主要是分享給大家+解釋分析。

昨天有小夥伴看完後希望我像以前一樣把按鈕那一部分的程式碼單獨提取出來單獨打成一個包,想單獨使用或者學習而不是去扣原始碼看(懶人打屁股),那既然有需求我也就做了,今天的事例程式碼我單獨做了一個包了,大家可以直接去下載,地址:https://github.com/ddwhan0123/BlogSample/blob/master/MaterialDesignToast.zip 直接下載然後解壓就行了,可以run,我2臺機器都試過了,並未出現問題(記得點個贊,支援下勞動成果,謝謝)

廢話結束,開始我們具體內容,還是分為2部分,P1為概念講解,P2為例項分析。

Snackbars

Snackbar 是一種針對操作的輕量級反饋機制,常以一個小的彈出框的形式,出現在手機螢幕下方或者桌面左下方。它們出現在螢幕所有層的最上方,包括浮動操作按鈕。

它們會在超時或者使用者在螢幕其他地方觸控之後自動消失。Snackbar
可以在螢幕上滑動關閉。當它們出現時,不會阻礙使用者在螢幕上的輸入,並且也不支援輸入。螢幕上同時最多隻能現實一個 Snackbar。

Android 也提供了一種主要用於提示系統訊息的膠囊狀的提示框 Toast。Toast 同 Snackbar 非常相似,但是 Toast
並不包含操作也不能從螢幕上滑動關閉。

我們來上下效果圖,看看是怎麼樣的:

這裡寫圖片描述

從螢幕底部彈出的一個試圖,一種是有互動的,一種是沒有互動的。跟我們的Toast一樣會自動消失,他消失的方式跟入場時的效果相反。

看完效果我們來讀一些理論知識。

通常 Snackbar 的高度應該僅僅用於容納所有的文字,而文字應該與執行的操作相關。Snackbar
中不能包含圖示,操作只能以文字的形式存在。

這裡寫圖片描述

樣式儘量的精簡不要附帶複雜的佈局內容

儘量不要附帶過多的操作(樣例裡為一個點選事件),注意Snackbar不要打斷任何UI介面其他元素正操進行的行為,就是如果有個dialog在跑,不要用Snackbar把他dimiss掉。

也不要遮蔽我們的懸浮按鈕,儘量 讓懸浮按鈕置於Snackbar的上方。

理論講完了,我們來看一下程式碼是如何實現的。

先貼下目錄結構

這裡寫圖片描述

正好Snackbar的佈局裡需要我們昨天用到的按鈕,我就整合進來了,然後就是一些素材檔案,大家根據自己的需求操作吧,Button部分的實現,這篇不解釋了,大家往前翻吧。

public class SnackBar extends Dialog 

24行,我們的SnackBar是一個Dialog的實現,而不是昨天的Rel的實現了(重要的是,要一看到繼承Dialog就意識到,他有show() dismiss() 之類的功能)

    String text;
    float textSize = 14;//Roboto Regular 14sp
    String buttonText;
    View.OnClickListener onClickListener;
    Activity activity;
    View view;
    ButtonFlat button;
    int backgroundSnackBar = Color.parseColor("#333333");
    int backgroundButton = Color.parseColor("#1E88E5");

    OnHideListener onHideListener;
    // Timer
    private boolean mIndeterminate = false;
    private int mTimer = 3 * 1000;

26-39行,一系列的初始化,定義了顏色啊,聲明瞭一些引數的變數,設定了預設的持續時間

 // With action button
    public SnackBar(Activity activity, String text, String buttonText, View.OnClickListener onClickListener) {
        super(activity, android.R.style.Theme_Translucent);
        this.activity = activity;
        this.text = text;
        this.buttonText = buttonText;
        this.onClickListener = onClickListener;
    }

    // Only text
    public SnackBar(Activity activity, String text) {
        super(activity, android.R.style.Theme_Translucent);
        this.activity = activity;
        this.text = text;
    }

41-55行,2種不同的建構函式,一種是帶按鈕,帶監聽的。還有種事更純粹的文字內容提示。

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.snackbar);
        setCanceledOnTouchOutside(false);
        ((TextView) findViewById(R.id.text)).setText(text);
        ((TextView) findViewById(R.id.text)).setTextSize(textSize); //set textSize
        button = (ButtonFlat) findViewById(R.id.buttonflat);
        if (text == null || onClickListener == null) {
            button.setVisibility(View.GONE);
        } else {
            button.setText(buttonText);
            button.setBackgroundColor(backgroundButton);

            button.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    dismiss();
                    onClickListener.onClick(v);
                }
            });
        }
        view = findViewById(R.id.snackbar);
        view.setBackgroundColor(backgroundSnackBar);
    }

58-83行,對一系列所需的控制元件進行初始化操作,設定了背景顏色,設定了監聽,設定了標題文字內容等。

     @Override
    public boolean onTouchEvent(MotionEvent event) {
        return activity.dispatchTouchEvent(event);
    }

    @Override
    public void onBackPressed() {
    }
  @Override
    public void show() {
        super.show();
        view.setVisibility(View.VISIBLE);
        view.startAnimation(AnimationUtils.loadAnimation(activity, R.anim.snackbar_show_animation));
        if (!mIndeterminate) {
            dismissTimer.start();
        }
    }

94-102行,呈現我們檢視,並且是執行了慢慢上升的動畫,動畫結束後開始計時

    Thread dismissTimer = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                Thread.sleep(mTimer);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.sendMessage(new Message());
        }
    });

    Handler handler = new Handler(new Handler.Callback() {

        @Override
        public boolean handleMessage(Message msg) {
            if (onHideListener != null) {
                onHideListener.onHide();
            }
            dismiss();
            return false;
        }
    });

105-127行,執行緒睡到相應事件,然後關閉我們的SnackBar

    @Override
    public void dismiss() {
        Animation anim = AnimationUtils.loadAnimation(activity, R.anim.snackbar_hide_animation);
        anim.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                SnackBar.super.dismiss();
            }
        });
        view.startAnimation(anim);
    }

133-152行,具體消失的方法,動畫結束後 dismiss控制元件

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // TODO 自動生成的方法存根
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            dismiss();
        }
        return super.onKeyDown(keyCode, event);
    }

154-161行,返回鍵的操作。

再接下來就是一系列的set方法了,這裡不做解釋,下面貼個MainActivity的操作,大家就理解了。

public class MainActivity extends AppCompatActivity {
    ButtonFlat button,button1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (ButtonFlat) findViewById(R.id.button);
        button1=(ButtonFlat)findViewById(R.id.button1);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SnackBar snackbar = new SnackBar(MainActivity.this, "這是一段很長的文字", "按鈕的文字內容",
                        new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(MainActivity.this, "按鈕被點選後吐出的內容", Toast.LENGTH_SHORT).show();
                            }
                        });
                snackbar.setDismissTimer(9000);
                snackbar.show();
            }
        });

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SnackBar snackBar=new SnackBar(MainActivity.this,"只有文字");
                snackBar.setBackgroundSnackBar(getResources().getColor(R.color.BrulyWood));
                snackBar.setMessageTextSize(20);
                snackBar.show();
            }
        });

    }

}

如何呼叫,如何設定看這裡就理解了,很簡單易懂。
建議修改下預設的持續時間,感覺有點短。

相比昨天的Button這部分還算簡單,大家一定也可以做出類似的效果。

一般我QQ回覆會比較慢,微信可以隨時找我。