Snackbar sb = Snackbar.make(v,"瀟湘劍雨",Snackbar.LENGTH_LONG)
.setAction("刪除嗎?", new View.OnClickListener() {
@Override
public void onClick(View v) {
//點(diǎn)擊了"是嗎?"字符串操作
ToastUtils.showRoundRectToast("逗比");
}
})
.setActionTextColor(Color.RED)
.setText("楊充是個(gè)逗比")
.addCallback(new BaseTransientBottomBar.BaseCallback() {
@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設(shè)置action顏色
我們提供的服務(wù)有:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、太湖ssl等。為1000多家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的太湖網(wǎng)站制作公司@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類中g(shù)etActionView方法@Override
br/>@Override
super.onFinishInflate();
mMessageView = (TextView) findViewById(R.id.snackbar_text);
mActionView = (Button) findViewById(R.id.snackbar_action);
}
public Button getActionView() {
return mActionView;
}
2.2.2 看setAction()方法的實(shí)現(xiàn)
首先是獲取父布局contentLayout,然后通過(guò)contentLayout調(diào)用getActionView()方法,返回的tv其實(shí)就是右邊的Button,然后判斷文本和監(jiān)聽器,設(shè)置可見性、文本、監(jiān)聽器。
@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)) {
// 表示回調(diào)已在隊(duì)列中。我們只需更新持續(xù)時(shí)間
mCurrentSnackbar.duration = duration;
// 如果這是當(dāng)前正在顯示的Snackbar,請(qǐng)調(diào)用重新調(diào)度它的
// timeout
mHandler.removeCallbacksAndMessages(mCurrentSnackbar);
// 這個(gè)方法很重要,當(dāng)執(zhí)行時(shí)間結(jié)束后,就會(huì)自動(dòng)dismiss。下面再詳細(xì)分析
scheduleTimeoutLocked(mCurrentSnackbar);
return;
} else if (isNextSnackbarLocked(callback)) {
//我們只需更新持續(xù)時(shí)間
mNextSnackbar.duration = duration;
} else {
//否則,我們需要?jiǎng)?chuàng)建一個(gè)新記錄并對(duì)其進(jìn)行排隊(duì)。
mNextSnackbar = new SnackbarRecord(duration, callback);
}
if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar,Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE)) {
// 如果我們目前有一個(gè)Snackbar,請(qǐng)嘗試取消它并排隊(duì)等待。
return;
} else {
// 清除當(dāng)前的快捷鍵
mCurrentSnackbar = null;
//很重要
showNextSnackbarLocked();
}
}
}
//注意這個(gè)callback方法
final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() {@Override
br/>@Override
sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, BaseTransientBottomBar.this));
}
@Override
public void dismiss(int event) {
sHandler.sendMessage(sHandler.obtainMessage(MSG_DISMISS, event, 0,
BaseTransientBottomBar.this));
}
};
//處理sHandler發(fā)送的消息
static {
sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {@Override
br/>@Override
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這個(gè)方法,注意:mCurrentSnackbar當(dāng)前正在顯示的,而mNextSnackbar是下一個(gè)要顯示的。能看到會(huì)調(diào)用callback的show方法,而這個(gè)calllback對(duì)象就是我們?cè)谡{(diào)用snackbar的show方法是傳進(jìn)去的那個(gè)。向Snackbar的Handler發(fā)送一個(gè)消息,最后顯示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
可以發(fā)現(xiàn),如果我們?cè)O(shè)置為無(wú)限期,則不會(huì)設(shè)置超時(shí),直接return函數(shù)。然后發(fā)送了一個(gè)叫做MSG_TIMEOUT的消息,繼續(xù)追終,最后會(huì)到達(dá)cancelSnackbarLocked方法。在cancelSnackbarLocked這個(gè)方法中,首先移除SnackbarRecord發(fā)出的所有消息,然后調(diào)用Callback的dismiss方法,從上面我們知道最終是向Snackbar的sHandler發(fā)送了一條消息,最終是調(diào)用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() {@Override
br/>@Override
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);
}
}
}
//最終可以追蹤到這個(gè)方法
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部分源碼
可以看到在動(dòng)畫結(jié)束的最后都調(diào)用了onViewHidden方法,所以最終都是要調(diào)用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);
}
}
可以一行代碼調(diào)用,也可以自己使用鏈?zhǔn)骄幊陶{(diào)用。支持設(shè)置顯示時(shí)長(zhǎng)屬性;可以設(shè)置背景色;可以設(shè)置文字大小,顏色;可以設(shè)置action內(nèi)容,文字大小,顏色,還有點(diǎn)擊事件;可以設(shè)置icon;代碼如下所示,更多內(nèi)容可以直接運(yùn)行demo哦!
//1.只設(shè)置text
SnackBarUtils.showSnackBar(this,"滾犢子");
//2.設(shè)置text,action,和點(diǎn)擊事件
SnackBarUtils.showSnackBar(this, "滾犢子", "ACTION", new View.OnClickListener() {
@Override
public void onClick(View v) {
ToastUtils.showRoundRectToast("滾犢子啦?");
}
});
//3.設(shè)置text,action,和點(diǎn)擊事件,和icon
SnackBarUtils.showSnackBar(this, "滾犢子", "ACTION",R.drawable.icon_cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
ToastUtils.showRoundRectToast("滾犢子啦?");
}
});
//4.鏈?zhǔn)秸{(diào)用
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();
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。