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)文章
Retrofit自定義請(qǐng)求參數(shù)注解的實(shí)現(xiàn)思路
這篇文章主要給大家介紹了Retrofit自定義請(qǐng)求參數(shù)注解的實(shí)現(xiàn)思路,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12
android 監(jiān)聽(tīng)SD卡文件變化的實(shí)現(xiàn)代碼
這篇文章主要介紹了android 監(jiān)聽(tīng)SD卡文件變化的實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-11-11
Android自定義TextBanner實(shí)現(xiàn)自動(dòng)滾動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android自定義TextBanner實(shí)現(xiàn)自動(dòng)滾動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
Android實(shí)現(xiàn)滑動(dòng)刻度尺效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)滑動(dòng)刻度尺效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
解決android studio 打包發(fā)現(xiàn)generate signed apk 消失不見(jiàn)問(wèn)題
這篇文章主要介紹了解決android studio 打包發(fā)現(xiàn)generate signed apk 消失不見(jiàn)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
Android app會(huì)crash的原因及解決方法
這篇文章主要介紹了Android app會(huì)crash的原因及解決方法,幫助大家更好的進(jìn)行Android開(kāi)發(fā),感興趣的朋友可以了解下2020-12-12
Android開(kāi)發(fā)之圖形圖像與動(dòng)畫(huà)(四)AnimationListener簡(jiǎn)介
就像Button控件有監(jiān)聽(tīng)器一樣,動(dòng)畫(huà)效果也有監(jiān)聽(tīng)器,只需要實(shí)現(xiàn)AnimationListener就可以實(shí)現(xiàn)對(duì)動(dòng)畫(huà)效果的監(jiān)聽(tīng),感興趣的朋友可以了解下啊,希望本文對(duì)你有所幫助2013-01-01
Android使用ScrollView實(shí)現(xiàn)滾動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android使用ScrollView實(shí)現(xiàn)滾動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01

