利用IToast實現(xiàn)滾動文字的toast(Toast方面)

最近產(chǎn)品提了一個想讓我拿刀的問題昨寞,一個提示文字要在其他app在頂層的時候也顯示棵帽,不能干擾用戶操作儡首,文字必須是可以滾動,時長為30秒(啥啥啥都是啥)器贩,做安卓的都知道toast只能設(shè)置為2s和3.5s颅夺,其它的值都無效,API的文檔雖然寫的第三個參數(shù)是時間蛹稍,但是Framework里作了重定義吧黄,限定了2s和3.5s這兩個值,對應(yīng) Toast.LENGTH_SHORT和Toast.LENGTH_LONG唆姐,但是測試不會管你安卓是怎么限制的拗慨,實現(xiàn)不出就是你自己能力不行,為了保住飯碗奉芦,問遍了度娘及其他的大佬赵抢,終于搞出了一個讓Toast持續(xù)顯示的方案:

```

public void showMyToast(final Toast toast, final int cnt) {

?final Timer timer =new Timer();

? ? timer.schedule(new TimerTask() {

? ? ? ? @Override

? ? ? ? public void run() {

? ? ? ? toast.show();

? ? }

? ? },0,3000);

? ? new Timer().schedule(new TimerTask() {

? ? ? ? @Override

? ? ? ? public void run() {

? ? ? ? toast.cancel();

? ? ? ? timer.cancel();

? ? }

? ? }, cnt );

}

```

調(diào)用:

Toast toast=Toast.makeText(RegistActivity.this,"這是可以隨意設(shè)置時間的Toast", Toast.LENGTH_LONG);showMyToast(toast,10*1000);// 設(shè)置顯示時間

你每次要關(guān)的時候我就調(diào)用show()方法,直到我Timer計時完畢声功,網(wǎng)上最傳廣的方法烦却,優(yōu)點是全原生,只需要加個控制類就行先巴,但是立馬被測試打回來了其爵,為啥冒冬?因為其實這只是偽顯示,每3秒都是重新打開的摩渺,所以滾動文字每三秒就回到開始重新輪播简烤,產(chǎn)品的需求是10秒一滾,它滾不了你就給我滾证逻,乐埠,,好吧囚企,既然別人是一種不要你覺得我要我覺得的態(tài)度丈咐,我也只能重新做了。龙宏。棵逊。有發(fā)現(xiàn)zhitaocai大佬為了解決當時MIUI4 toast不顯示的問題把toast重寫了一遍實現(xiàn)了完整的setDuration方法,(github地址:https://github.com/zhitaocai/ToastCompat_Deprecated)不過內(nèi)部的view是寫死的银酗,如果只需要使用普通的toast的話只需引入依賴庫之后直接ToastCompat.make(Contextcontext,Stringtext,longduration).show();

就可以愉快的使用了辆影,但是如果需要像我一樣實現(xiàn)滾動文字和文字前l(fā)ogo的話就必須對MIUItoast類進行重寫,在IToast setText方法中自定義view和內(nèi)容然后setview(view)黍特,具體代碼如下:

```

? ??public class MIUIToastimplements IToast {

private static HandlermHandler =new Handler();

? ? public AutoMarqueeTextViewGeTuiToastUtilMessage;

? ? public ImageViewGeTuiToastUtilImage;

? ? public ViewGeTuiToastUtilView;

? ? /**

* 維護toast的隊列

*/

? ? private static BlockingQueuemQueue =new LinkedBlockingQueue<>();

? ? /**

? ? * 原子操作:判斷當前是否在讀取{@linkplain #mQueue 隊列}來顯示toast

*/

? ? protected static AtomicIntegermAtomicInteger =new AtomicInteger(0);

? ? private WindowManagermWindowManager;

? ? private long mDurationMillis;

? ? private ViewmView;

? ? private WindowManager.LayoutParamsmParams;

? ? private ContextmContext;

? ? public static IToastmakeText(Context context, String text, long duration) {

return new MIUIToast(context).setText(text).setDuration(duration)

.setGravity(Gravity.TOP, 0, DisplayUtil.dip2px(context, 10));

? ? }

public MIUIToast(Context context) {

mContext = context;

? ? ? ? mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);

? ? ? ? mParams =new WindowManager.LayoutParams();

? ? ? ? mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

? ? ? ? mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

? ? ? ? mParams.format = PixelFormat.TRANSLUCENT;

? ? ? ? mParams.windowAnimations = android.R.style.Animation_Toast;

? ? ? ? mParams.type = WindowManager.LayoutParams.TYPE_TOAST;

? ? ? ? mParams.setTitle("Toast");

? ? ? ? mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |

WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

? ? ? ? // 默認小米Toast在下方居中

? ? ? ? mParams.gravity = Gravity.TOP ;

? ? }

/**

* Set the location at which the notification should appear on the screen.

*

? ? * @param gravity

? ? * @param xOffset

? ? * @param yOffset

? ? */

? ? @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)

@Override

? ? public IToastsetGravity(int gravity, int xOffset, int yOffset) {

// We can resolve the Gravity here by using the Locale for getting

// the layout direction

? ? ? ? final int finalGravity;

? ? ? ? if (Build.VERSION.SDK_INT >=14) {

final Configuration config =mView.getContext().getResources().getConfiguration();

? ? ? ? ? ? finalGravity = Gravity.getAbsoluteGravity(gravity, config.getLayoutDirection());

? ? ? ? }else {

finalGravity = gravity;

? ? ? ? }

mParams.gravity = finalGravity;

? ? ? ? if ((finalGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {

mParams.horizontalWeight =1.0f;

? ? ? ? }

if ((finalGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {

mParams.verticalWeight =1.0f;

? ? ? ? }

mParams.y = yOffset;

? ? ? ? mParams.x = xOffset;

return this;

? ? }

@Override

? ? public IToastsetDuration(long durationMillis) {

if (durationMillis <0) {

mDurationMillis =0;

? ? ? ? }

if (durationMillis == Toast.LENGTH_SHORT) {

mDurationMillis =2000;

? ? ? ? }else if (durationMillis == Toast.LENGTH_LONG) {

mDurationMillis =3500;

? ? ? ? }else {

mDurationMillis = durationMillis;

? ? ? ? }

return this;

? ? }

/**

? ? * 不能和{@link #setText(String)}一起使用蛙讥,要么{@link #setView(View)} 要么{@link #setView(View)}

*

? ? * @param view

? ? *

? ? * @return

? ? */

? ? @Override

? ? public IToastsetView(View view) {

mView = view;

return this;

? ? }

@Override

? ? public IToastsetMargin(float horizontalMargin, float verticalMargin) {

mParams.horizontalMargin = horizontalMargin;

? ? ? ? mParams.verticalMargin = verticalMargin;

return this;

? ? }

/**

? ? * 不能和{@link #setView(View)}一起使用,要么{@link #setView(View)} 要么{@link #setView(View)}

*

? ? * @return

? ? */

? ? @Override

? ? public IToastsetText(String text) {

// 模擬Toast的布局文件 com.android.internal.R.layout.transient_notification

// 雖然可以手動用java寫灭衷,但是不同廠商系統(tǒng)次慢,這個布局的設(shè)置好像是不同的,因此我們自己獲取原生Toast的view進行配置

? ? ? ? GeTuiToastUtilView = LayoutInflater.from(mContext).inflate(R.layout.toast_layout, null);

? ? ? ? if (GeTuiToastUtilView !=null) {

GeTuiToastUtilMessage =GeTuiToastUtilView.findViewById(R.id.geTuiToastUtilMessage);

? ? ? ? ? ? GeTuiToastUtilImage = (ImageView)GeTuiToastUtilView.findViewById(R.id.toast_image);

? ? ? ? ? ? GeTuiToastUtilMessage.setTextColor(ScnResourceUtil.getColor(mContext, R.color.scn_color_EBEBEB));

? ? ? ? ? ? GeTuiToastUtilMessage.setTextSize(TypedValue.COMPLEX_UNIT_PX, ScnResourceUtil.getDimen(mContext, R.dimen.dimen_12sp));

? ? ? ? ? ? GeTuiToastUtilMessage.setMaxWidth(ScnResourceUtil.getDimen(mContext,R.dimen.dimen_574dp));

? ? ? ? ? ? GeTuiToastUtilMessage.setScrollStep(ScnResourceUtil.getDimen(mContext,R.dimen.dimen_200dp));

? ? ? ? ? ? GeTuiToastUtilMessage.setMaxLines(1);

? ? ? ? ? ? GeTuiToastUtilMessage.setRndDuration(10);

? ? ? ? ? ? GeTuiToastUtilMessage.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);

? ? ? ? ? ? setView(GeTuiToastUtilView);

? ? ? ? ? ? GeTuiToastUtilMessage.setText(text.isEmpty() ?"null" : text);

? ? ? ? ? ? GeTuiToastUtilMessage.post(() ->GeTuiToastUtilMessage.startMarquee());

? ? ? ? ? ? this.setGravity(Gravity.TOP,0,20);

? ? ? ? }

return this;

? ? }

@Override

? ? public void show() {

// 1. 將本次需要顯示的toast加入到隊列中

? ? ? ? mQueue.offer(this);

? ? ? ? // 2. 如果隊列還沒有激活翔曲,就激活隊列迫像,依次展示隊列中的toast

? ? ? ? if (0 ==mAtomicInteger.get()) {

mAtomicInteger.incrementAndGet();

? ? ? ? ? ? mHandler.post(mActivite);

? ? ? ? }

}

@Override

? ? public void cancel() {

// 1. 如果隊列已經(jīng)處于非激活狀態(tài)或者隊列沒有toast了,就表示隊列沒有toast正在展示了瞳遍,直接return

? ? ? ? if (0 ==mAtomicInteger.get() &&mQueue.isEmpty()) {

return;

? ? ? ? }

// 2. 當前顯示的toast是否為本次要取消的toast闻妓,如果是的話

// 2.1 先移除之前的隊列邏輯

// 2.2 立即暫停當前顯示的toast

// 2.3 重新激活隊列

? ? ? ? if (this.equals(mQueue.peek())) {

mHandler.removeCallbacks(mActivite);

? ? ? ? ? ? mHandler.post(mHide);

? ? ? ? ? ? mHandler.post(mActivite);

? ? ? ? }

//TODO 如果一個Toast在隊列中的等候展示,當調(diào)用了這個toast的取消時掠械,考慮是否應(yīng)該從對隊列中移除由缆,看產(chǎn)品需求吧

? ? }

private void handleShow() {

if (mView !=null) {

if (mView.getParent() !=null) {

mWindowManager.removeView(mView);

? ? ? ? ? ? }

mWindowManager.addView(mView, mParams);

? ? ? ? }

}

private void handleHide() {

if (mView !=null) {

// note: checking parent() just to make sure the view has

// been added...? i have seen cases where we get here when

// the view isn't yet added, so let's try not to crash.

? ? ? ? ? ? if (mView.getParent() !=null) {

mWindowManager.removeView(mView);

? ? ? ? ? ? ? ? // 同時從隊列中移除這個toast

? ? ? ? ? ? ? ? mQueue.poll();

? ? ? ? ? ? }

mView =null;

? ? ? ? }

}

private static void activeQueue() {

MIUIToast miuiToast =mQueue.peek();

? ? ? ? if (miuiToast ==null) {

// 如果不能從隊列中獲取到toast的話,那么就表示已經(jīng)暫時完所有的toast了

// 這個時候需要標記隊列狀態(tài)為:非激活讀取中

? ? ? ? ? ? mAtomicInteger.decrementAndGet();

? ? ? ? }else {

// 如果還能從隊列中獲取到toast的話份蝴,那么就表示還有toast沒有展示

// 1. 展示隊首的toast

// 2. 設(shè)置一定時間后主動采取toast消失措施

// 3. 設(shè)置展示完畢之后再次執(zhí)行本邏輯犁功,以展示下一個toast

? ? ? ? ? ? mHandler.post(miuiToast.mShow);

? ? ? ? ? ? mHandler.postDelayed(miuiToast.mHide, miuiToast.mDurationMillis);

? ? ? ? ? ? mHandler.postDelayed(mActivite, miuiToast.mDurationMillis);

? ? ? ? }

}

private final RunnablemShow =new Runnable() {

@Override

? ? ? ? public void run() {

handleShow();

? ? ? ? }

};

? ? private final RunnablemHide =new Runnable() {

@Override

? ? ? ? public void run() {

handleHide();

? ? ? ? }

};

? ? private final static RunnablemActivite =new Runnable() {

@Override

? ? ? ? public void run() {

activeQueue();

? ? ? ? }

};

}

```

這里感謝非花非霧--大佬的修改方案這里用的是自定義方案三

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婚夫,一起剝皮案震驚了整個濱河市浸卦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌案糙,老刑警劉巖限嫌,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件靴庆,死亡現(xiàn)場離奇詭異,居然都是意外死亡怒医,警方通過查閱死者的電腦和手機炉抒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稚叹,“玉大人焰薄,你說我怎么就攤上這事“切洌” “怎么了塞茅?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長季率。 經(jīng)常有香客問我野瘦,道長,這世上最難降的妖魔是什么飒泻? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任鞭光,我火速辦了婚禮,結(jié)果婚禮上泞遗,老公的妹妹穿的比我還像新娘惰许。我一直安慰自己,他們只是感情好史辙,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布啡省。 她就那樣靜靜地躺著,像睡著了一般髓霞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上畦戒,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天方库,我揣著相機與錄音,去河邊找鬼障斋。 笑死纵潦,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的垃环。 我是一名探鬼主播邀层,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遂庄!你這毒婦竟也來了寥院?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤涛目,失蹤者是張志新(化名)和其女友劉穎秸谢,沒想到半個月后凛澎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡估蹄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年塑煎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臭蚁。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡最铁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垮兑,到底是詐尸還是另有隱情冷尉,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布甥角,位于F島的核電站网严,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嗤无。R本人自食惡果不足惜震束,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望当犯。 院中可真熱鬧垢村,春花似錦、人聲如沸嚎卫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拓诸。三九已至侵佃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奠支,已是汗流浹背馋辈。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留倍谜,地道東北人迈螟。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像尔崔,于是被迫代替她去往敵國和親答毫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354