Snackbar sb = Snackbar.make(v,"瀟湘劍雨",Snackbar.LENGTH_LONG) .setAction("刪除嗎?", new View.OnClickListener() { @Override public void onClick(View v) { //點擊了"是嗎?"字符串操做 ToastUtils.showRoundRectToast("逗比"); } }) .setActionTextColor(Color.RED) .setText("楊充是個逗比") .addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() { @Override public void onDismissed(Snackbar transientBottomBar, int event) { super.onDismissed(transientBottomBar, event); switch (event) { case Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE: case Snackbar.Callback.DISMISS_EVENT_MANUAL: case Snackbar.Callback.DISMISS_EVENT_SWIPE: case Snackbar.Callback.DISMISS_EVENT_TIMEOUT: ToastUtils.showRoundRectToast("刪除成功"); break; case Snackbar.Callback.DISMISS_EVENT_ACTION: ToastUtils.showRoundRectToast("撤銷了刪除操做"); break; } Log.d("MainActivity","onDismissed"); } @Override public void onShown(Snackbar transientBottomBar) { super.onShown(transientBottomBar); Log.d("MainActivity","onShown"); } }); sb.show();
2.2.1 setActionTextColor設置action顏色php
@NonNull public Snackbar setActionTextColor(@ColorInt int color) { final SnackbarContentLayout contentLayout = (SnackbarContentLayout) mView.getChildAt(0); final TextView tv = contentLayout.getActionView(); tv.setTextColor(color); return this; }
//而後看SnackbarContentLayout類中getActionView方法br/>@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMessageView = (TextView) findViewById(R.id.snackbar_text);
mActionView = (Button) findViewById(R.id.snackbar_action);
}
public Button getActionView() {
return mActionView;
}android
2.2.2 看setAction()方法的實現git
首先是獲取父佈局contentLayout,而後經過contentLayout調用getActionView()方法,返回的tv其實就是右邊的Button,而後判斷文本和監聽器,設置可見性、文本、監聽器。github
@NonNull public Snackbar setAction(CharSequence text, final View.OnClickListener listener) { final SnackbarContentLayout contentLayout = (SnackbarContentLayout) mView.getChildAt(0); final TextView tv = contentLayout.getActionView(); if (TextUtils.isEmpty(text) || listener == null) { tv.setVisibility(View.GONE); tv.setOnClickListener(null); } else { tv.setVisibility(View.VISIBLE); tv.setText(text); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listener.onClick(view); // Now dismiss the Snackbar dispatchDismiss(BaseCallback.DISMISS_EVENT_ACTION); } }); } return this; }
2.3.1 show顯示面試
public void show() { SnackbarManager.getInstance().show(mDuration, mManagerCallback); }
public void show(int duration, Callback callback) {
synchronized (mLock) {
if (isCurrentSnackbarLocked(callback)) {
// 表示回調已在隊列中。咱們只需更新持續時間
mCurrentSnackbar.duration = duration;編程
// 若是這是當前正在顯示的Snackbar,請調用從新調度它的 // timeout mHandler.removeCallbacksAndMessages(mCurrentSnackbar); // 這個方法很重要,當執行時間結束後,就會自動dismiss。下面再詳細分析 scheduleTimeoutLocked(mCurrentSnackbar); return; } else if (isNextSnackbarLocked(callback)) { //咱們只需更新持續時間 mNextSnackbar.duration = duration; } else { //不然,咱們須要建立一個新記錄並對其進行排隊。 mNextSnackbar = new SnackbarRecord(duration, callback); } if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar,Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE)) { // 若是咱們目前有一個Snackbar,請嘗試取消它並排隊等待。 return; } else { // 清除當前的快捷鍵 mCurrentSnackbar = null; //很重要 showNextSnackbarLocked(); } }
}segmentfault
//注意這個callback方法
final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() {br/>@Override
public void show() {
sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, BaseTransientBottomBar.this));
}markdown
@Override public void dismiss(int event) { sHandler.sendMessage(sHandler.obtainMessage(MSG_DISMISS, event, 0, BaseTransientBottomBar.this)); }
};ide
//處理sHandler發送的消息
static {
sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {br/>@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case MSG_SHOW:
((BaseTransientBottomBar) message.obj).showView();
return true;
case MSG_DISMISS:
((BaseTransientBottomBar) message.obj).hideView(message.arg1);
return true;
}
return false;
}
});
}函數
- 而後看看showNextSnackbarLocked這個方法,注意:mCurrentSnackbar當前正在顯示的,而mNextSnackbar是下一個要顯示的。能看到會調用callback的show方法,而這個calllback對象就是咱們在調用snackbar的show方法是傳進去的那個。向Snackbar的Handler發送一個消息,最後顯示Snackbar。
private void showNextSnackbarLocked() {
if (mNextSnackbar != null) {
mCurrentSnackbar = mNextSnackbar;
mNextSnackbar = null;
final Callback callback = mCurrentSnackbar.callback.get(); if (callback != null) { callback.show(); } else { // The callback doesn't exist any more, clear out the Snackbar mCurrentSnackbar = null; } }
}
2.3.2 看看scheduleTimeoutLocked源碼如何銷燬snackBar
能夠發現,若是咱們設置爲無限期,則不會設置超時,直接return函數。而後發送了一個叫作MSG_TIMEOUT的消息,繼續追終,最後會到達cancelSnackbarLocked方法。在cancelSnackbarLocked這個方法中,首先移除SnackbarRecord發出的全部消息,而後調用Callback的dismiss方法,從上面咱們知道最終是向Snackbar的sHandler發送了一條消息,最終是調用Snackbar的hideView消失。
private void scheduleTimeoutLocked(SnackbarRecord r) { if (r.duration == Snackbar.LENGTH_INDEFINITE) { // If we're set to indefinite, we don't want to set a timeout return; } int durationMs = LONG_DURATION_MS; if (r.duration > 0) { durationMs = r.duration; } else if (r.duration == Snackbar.LENGTH_SHORT) { durationMs = SHORT_DURATION_MS; } mHandler.removeCallbacksAndMessages(r); mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_TIMEOUT, r), durationMs); }
//接受mHandler消息而且處理
mHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {br/>@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case MSG_TIMEOUT:
handleTimeout((SnackbarRecord) message.obj);
return true;
}
return false;
}
});
//
void handleTimeout(SnackbarRecord record) {
synchronized (mLock) {
if (mCurrentSnackbar == record || mNextSnackbar == record) {
cancelSnackbarLocked(record, Snackbar.Callback.DISMISS_EVENT_TIMEOUT);
}
}
}
//最終能夠追蹤到這個方法
private boolean cancelSnackbarLocked(SnackbarRecord record, int event) {
final Callback callback = record.callback.get();
if (callback != null) {
// Make sure we remove any timeouts for the SnackbarRecord
mHandler.removeCallbacksAndMessages(record);
callback.dismiss(event);
return true;
}
return false;
}
最後具體看一下animateViewOut部分源碼
能夠看到在動畫結束的最後都調用了onViewHidden方法,因此最終都是要調用onViewHidden方法的。
private void animateViewOut(final int event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { ViewCompat.animate(mView) .translationY(mView.getHeight()) .setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR) .setDuration(ANIMATION_DURATION) .setListener(new ViewPropertyAnimatorListenerAdapter() { @Override public void onAnimationStart(View view) { mContentViewCallback.animateContentOut(0, ANIMATION_FADE_DURATION); } @Override public void onAnimationEnd(View view) { onViewHidden(event); } }).start(); } else { Animation anim = AnimationUtils.loadAnimation(mView.getContext(), R.anim.design_snackbar_out); anim.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); anim.setDuration(ANIMATION_DURATION); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationEnd(Animation animation) { onViewHidden(event); } @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationRepeat(Animation animation) {} }); mView.startAnimation(anim); } }
能夠一行代碼調用,也能夠本身使用鏈式編程調用。支持設置顯示時長屬性;能夠設置背景色;能夠設置文字大小,顏色;能夠設置action內容,文字大小,顏色,還有點擊事件;能夠設置icon;代碼以下所示,更多內容能夠直接運行demo哦!
//1.只設置text SnackBarUtils.showSnackBar(this,"滾犢子"); //2.設置text,action,和點擊事件 SnackBarUtils.showSnackBar(this, "滾犢子", "ACTION", new View.OnClickListener() { @Override public void onClick(View v) { ToastUtils.showRoundRectToast("滾犢子啦?"); } }); //3.設置text,action,和點擊事件,和icon SnackBarUtils.showSnackBar(this, "滾犢子", "ACTION",R.drawable.icon_cancel, new View.OnClickListener() { @Override public void onClick(View v) { ToastUtils.showRoundRectToast("滾犢子啦?"); } }); //4.鏈式調用 SnackBarUtils.builder() .setBackgroundColor(this.getResources().getColor(R.color.color_7f000000)) .setTextSize(14) .setTextColor(this.getResources().getColor(R.color.white)) .setTextTypefaceStyle(Typeface.BOLD) .setText("滾犢子") .setMaxLines(4) .centerText() .setActionText("收到") .setActionTextColor(this.getResources().getColor(R.color.color_f25057)) .setActionTextSize(16) .setActionTextTypefaceStyle(Typeface.BOLD) .setActionClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ToastUtils.showRoundRectToast("滾犢子啦?"); } }) .setIcon(R.drawable.icon_cancel) .setActivity(MainActivity.this) .setDuration(SnackBarUtils.DurationType.LENGTH_INDEFINITE) .build() .show();