Android Application級(jí)別自定義Toast
在Android開(kāi)發(fā)過(guò)程中,有時(shí)會(huì)需要一些消息提示,大多數(shù)情況可以用dialog來(lái)做,但有些消息不需要用戶(hù)去點(diǎn)擊取消并且不能對(duì)用戶(hù)體驗(yàn)產(chǎn)生影響的提示,就需要toast來(lái)做了。但可惜的是,toast是系統(tǒng)級(jí)的,凡是涉及到系統(tǒng)的又會(huì)涉及到其他APP,有些定制系統(tǒng)可以對(duì)App的消息通知進(jìn)行設(shè)置,一旦禁止了APP的通知toast則不會(huì)顯示。而且在Android 7以后toast還需要申請(qǐng)權(quán)限麻煩死了有木有,勞資就想安安靜靜的提示一下有這么麻煩嗎!所以,本人特地研究了下能在Application級(jí)別不受限制提示的toast。
先看效果:
效果很簡(jiǎn)單,就是一個(gè)頭部即現(xiàn)即隱的提示,外加過(guò)渡動(dòng)畫(huà)。其實(shí)自定義系統(tǒng)級(jí)的toast也能實(shí)現(xiàn)這種效果,但之前已經(jīng)說(shuō)了系統(tǒng)級(jí)的toast有限制。
話(huà)不多說(shuō),現(xiàn)在介紹下這是如何實(shí)現(xiàn)的吧!
首先申明這是基于WindowManager產(chǎn)生的view,本人看了系統(tǒng)級(jí)toast的源碼好像也是基于WindowManager的。WindowManager是個(gè)神奇的東西,在這就不多做介紹了,我們只需要知道activity.getWindowManager().addView(layout, params)可以給整個(gè)Activity界面添加一個(gè)view層,這一層可以不影響activity的操作。竟然有這個(gè)功能瞬間漲姿勢(shì)了有不有!細(xì)心人的應(yīng)該察覺(jué)到了這和FrameLayout挺像,其實(shí)Activity的root就是一個(gè)FrameLayout。
好了,既然Activity有這個(gè)功能,那tosat做起來(lái)就有頭緒了。
先實(shí)現(xiàn)java類(lèi)代碼(個(gè)人愛(ài)好,喜歡先主后次):
/** * App級(jí)toast */ public class AppToast { private Activity activity; private ViewGroup layout; private ViewGroup content; private TextView textView; private Animation startAnimation; private Animation centerAnimation; private Animation endAnimation; private DelayTask task; private boolean isShow; private LayoutParams params; /** * APP級(jí)別Toast */ public AppToast(Activity activity) { this.activity = activity; layout = (ViewGroup) LayoutInflater.from(activity).inflate(R.layout.toast, null); content = (ViewGroup) layout.getChildAt(0); textView = (TextView) content.getChildAt(0); params = new LayoutParams(); params.height = LayoutParams.WRAP_CONTENT; params.width = LayoutParams.MATCH_PARENT; params.gravity = Gravity.TOP; params.type = LayoutParams.TYPE_APPLICATION; params.format = PixelFormat.TRANSLUCENT; params.flags = LayoutParams.FLAG_KEEP_SCREEN_ON | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE; activity.getWindowManager().addView(layout, params); layout.setVisibility(View.GONE); // 開(kāi)始動(dòng)畫(huà) startAnimation = new AlphaAnimation(0, 1); startAnimation.setDuration(500); // 中間動(dòng)畫(huà) centerAnimation = new AlphaAnimation(0.92f, 1); centerAnimation.setDuration(500); // 結(jié)束動(dòng)畫(huà) endAnimation = new AlphaAnimation(1, 0); endAnimation.setDuration(500); endAnimation.setInterpolator(new AccelerateInterpolator()); // 結(jié)束動(dòng)畫(huà)監(jiān)聽(tīng) endAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { layout.setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animation animation) { } }); } /** * 顯示Toast */ public void show(String s) { show(s, 1500); } /** * 顯示Toast */ public void show(String s, int delay) { textView.setText(s); start(); if (task != null) { task.stop(); } task = new DelayTask(delay) { @Override public void logic() { end(); } }; task.start(); } /** * 開(kāi)始 */ private void start() { if (!isShow) { layout.setVisibility(View.VISIBLE); content.startAnimation(startAnimation); isShow = true; } else { content.startAnimation(centerAnimation); } } /** * 結(jié)束 */ private void end() { content.startAnimation(endAnimation); isShow = false; } }
先在構(gòu)造方法AppToast(Activity activity)中加載自定義toast的布局以及初始化params參數(shù)。然后添加各個(gè)過(guò)程所需的動(dòng)畫(huà)。這其中有個(gè)重點(diǎn),就是params.type = LayoutParams.TYPE_APPLICATION,記住一定要是TYPE_APPLICATION,而不是TYPE_TOAST,TYPE_TOAST會(huì)在Android 7上被莫名其妙的限制。
有些人可能會(huì)注意到除了開(kāi)始動(dòng)畫(huà)和結(jié)束動(dòng)畫(huà),為什么還有個(gè)中間動(dòng)畫(huà)?其實(shí)這是為了多重toast提示做的一個(gè)辨別機(jī)制,我們?cè)谟孟到y(tǒng)級(jí)toast的時(shí)候有些人應(yīng)該能感受到toast并不是重疊顯示,但也不是直接替換內(nèi)容,而是在替換內(nèi)容的時(shí)候微微的閃一下表示內(nèi)容變更了,所以在這里就用了一個(gè)中間動(dòng)畫(huà)來(lái)執(zhí)行那“閃一下”的效果。
關(guān)于其中用到的一個(gè)延時(shí)器類(lèi)DelayTask,這是本人為了方便自行設(shè)計(jì)的一個(gè)工具類(lèi),其效果就是延時(shí)執(zhí)行一段UI邏輯,其代碼如下:
/** * 延時(shí)器類(lèi) * * @author zls * * @version 1.0 * * @time 2015-12-27下午7:52:10 */ public abstract class DelayTask { protected Thread thread; private boolean isRun; /** * 延時(shí)器 */ public DelayTask(final long delay) { thread = new Thread() { @Override public void run() { try { sleep(delay); if(isRun) { mHandler.sendEmptyMessage(0); } } catch (Exception e) { } } }; } protected Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { logic(); } }; /** 開(kāi)始執(zhí)行 */ public void start() { isRun = true; thread.start(); } /** 停止執(zhí)行 */ public void stop() { isRun = false; } /** 執(zhí)行邏輯 */ public abstract void logic(); }
有興趣的朋友可以借鑒下,覺(jué)得這么設(shè)計(jì)不太好的也可以用你們自己設(shè)計(jì)的延時(shí)器來(lái)用。
現(xiàn)在上toast的布局代碼:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingTop="5dp" android:paddingLeft="15dp" android:paddingRight="15dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/toast_shape" android:fitsSystemWindows="true" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:gravity="center" android:text="默認(rèn)提示" android:textColor="#fff" android:textSize="15sp"/> </LinearLayout> </LinearLayout>
測(cè)試Activity的代碼:
public class MainActivity extends AppCompatActivity { private AppToast toast; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); toast = new AppToast(this); } public void ok(View v) { toast.show("這是Toast測(cè)試!" + Math.random()); } }
Demo下載
就此結(jié)束,希望能幫到需要此功能的朋友。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android中 動(dòng)態(tài)改變對(duì)話(huà)框值的方法
Android Dev-Guide 推薦重寫(xiě)Activity.onCreateDialog()方法來(lái)創(chuàng)建Dialog,這樣Dialog就歸屬于這個(gè)Activity了。2013-04-04Android 中ActionBar+fragment實(shí)現(xiàn)頁(yè)面導(dǎo)航的實(shí)例
這篇文章主要介紹了Android 中ActionBar+fragment實(shí)現(xiàn)頁(yè)面導(dǎo)航的實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助到大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-09-09Android 實(shí)現(xiàn)手機(jī)接通電話(huà)后振動(dòng)提示的功能
本文主要介紹Android 實(shí)現(xiàn)手機(jī)接通電話(huà)后振動(dòng)提示的功能,這里整理了詳細(xì)的相關(guān)資料,并附有示例代碼,有需要的朋友可以參考下2016-08-08Android開(kāi)發(fā)MediaCodec和lamemp3多段音頻截取拼接
這篇文章主要為大家介紹了Android開(kāi)發(fā)使用MediaCodec和lamemp3實(shí)現(xiàn)多段音頻截取拼接的編程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Jetpack Compose按鈕組件使用實(shí)例詳細(xì)講解
這篇文章主要介紹了Jetpack Compose按鈕組件使用實(shí)例,按鈕組件Button是用戶(hù)和系統(tǒng)交互的重要組件之一,它按照Material Design風(fēng)格實(shí)現(xiàn),我們先看下Button的參數(shù)列表,通過(guò)參數(shù)列表了解下Button的整體功能2023-04-042014值得推薦的10個(gè)移動(dòng) Web 應(yīng)用程序開(kāi)發(fā)框架
今天這篇文章向大家推薦10大優(yōu)秀的移動(dòng) Web 開(kāi)發(fā)框架,幫助開(kāi)發(fā)者更加高效的開(kāi)發(fā)移動(dòng)Web應(yīng)用。2014-08-08android開(kāi)發(fā)教程之ubuntu使用adb連接小米2的步驟和adb調(diào)試方法
這篇文章主要介紹了ubuntu中使用adb連接小米2的步驟和adb調(diào)試方法,需要的朋友可以參考下2014-02-02ionic監(jiān)聽(tīng)android返回鍵實(shí)現(xiàn)“再按一次退出”功能
本篇文章主要介紹了ionic監(jiān)聽(tīng)android返回鍵實(shí)現(xiàn)“再按一次退出”功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-02-02