使用反射機(jī)制控制Toast的顯示時(shí)間
本文為大家分享了使用反射機(jī)制控制Toast顯示時(shí)間的具體代碼,供大家參考,具體內(nèi)容如下
1、Toast源碼分析:
Toast的默認(rèn)view是在transient_notification.xml中定義的一個(gè)TextView,如果需要設(shè)置Toast的界面,可以通過(guò)setView方法實(shí)現(xiàn);如果需要設(shè)置Toast默認(rèn)顯示的位置,可以通過(guò)setGravity或者setMargin方法進(jìn)行設(shè)置,值得一提的是setMargin方法的參數(shù)范圍是0-1即它是屏幕的百分比,如setMargin(0.1,0.1)。
Toast 的構(gòu)造函數(shù),會(huì)實(shí)例化TN對(duì)象,TN對(duì)象擁有show和hide兩個(gè)方法,可以控制Toast的顯示和消失。那么又是什么來(lái)完成調(diào)用和何時(shí)調(diào)用這兩個(gè)方法的呢?我們可以從Toast的show方法中找到答案:
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();
String pkg = mContext.getPackageName();
TN tn = mTN;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
該方法,首先會(huì)判斷待顯示的view對(duì)象是否為null;然后獲取單例的INotificationManager的對(duì)象,最后把當(dāng)前Toast的請(qǐng)求加入到顯示隊(duì)列,同時(shí)把該Toast需要顯示的時(shí)間也傳了進(jìn)去。enqueueToast的方法如下:
public void enqueueToast(java.lang.String pkg, android.app.ITransientNotification callback, int duration) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(pkg);
_data.writeStrongBinder((((callback!=null))?(callback.asBinder()):(null)));
_data.writeInt(duration);
mRemote.transact(Stub.TRANSACTION_enqueueToast, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
可以看到該方法,通過(guò)transact方法調(diào)用了底層代碼,即使用了binder的機(jī)制。service最終根據(jù)duration,調(diào)用TN的show和hide方法顯示和隱藏Toast界面。
2、如何修改Toast的顯示時(shí)間
Toast默認(rèn)有兩種顯示時(shí)間,分別是LENGTH_SHORT和LENGTH_LONG。如果我們需要Toast顯示的時(shí)間,小于LENGTH_SHORT,那么非常容易實(shí)現(xiàn),直接調(diào)用Toast的cancel方法即可。那么我們?nèi)绻隩oast的顯示時(shí)間大于LENGTH_LONG,那就沒(méi)有辦法實(shí)現(xiàn)了,因?yàn)楹问抡{(diào)用TN的hide方法,不是由你控制的。
下面通過(guò)Java的反射機(jī)制,拿到TN的show和hide方法,自己來(lái)控制Toast的顯示和隱藏。
public class ReflectToast {
Context mContext;
private Toast mToast;
private Field field;
private Object obj;
private Method showMethod, hideMethod;
public ReflectToast(Context c, View v) {
this.mContext = c;
mToast = new Toast(mContext);
mToast.setView(v);
reflectionTN();
}
public void show() {
try {
showMethod.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public void cancel() {
try {
hideMethod.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void reflectionTN() {
try {
field = mToast.getClass().getDeclaredField("mTN");
field.setAccessible(true);
obj = field.get(mToast);
showMethod = obj.getClass().getDeclaredMethod("show", null);
hideMethod = obj.getClass().getDeclaredMethod("hide", null);
} catch (Exception e) {
e.printStackTrace();
}
}
在外部,我們可以調(diào)用ReflectToast的show和cancel方法,來(lái)實(shí)現(xiàn)控制Toast的顯示和隱藏。
為了不讓大家再出錯(cuò),給出調(diào)用代碼如下:
public class MainActivity extends Activity {
ReflectToast toast;
boolean isShown = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tView = new TextView(this);
tView.setText("ReflectToast !!!");
toast = new ReflectToast(this, tView);
findViewById(R.id.click).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(isShown){
toast.cancel();
isShown = false;
}else{
toast.show();
isShown = true;
}
}
});
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 實(shí)例講解Java基礎(chǔ)之反射
- ES6 如何改變JS內(nèi)置行為的代理與反射
- 實(shí)例講解Java中動(dòng)態(tài)代理和反射機(jī)制
- Java反射機(jī)制的精髓講解
- 利用lambda表達(dá)式樹(shù)優(yōu)化反射詳解
- 詳解Golang利用反射reflect動(dòng)態(tài)調(diào)用方法
- Kotlin中的反射機(jī)制深入講解
- 基于Java反射的map自動(dòng)裝配JavaBean工具類設(shè)計(jì)示例代碼
- Java高級(jí)特性之反射機(jī)制實(shí)例詳解
- 通過(guò)反射注解批量插入數(shù)據(jù)到DB的實(shí)現(xiàn)方法
相關(guān)文章
Android 啟動(dòng)模式FLAG_ACTIVITY_CLEAR_TOP案例詳解
這篇文章主要介紹了Android 啟動(dòng)模式FLAG_ACTIVITY_CLEAR_TOP案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Android音頻可視化開(kāi)發(fā)案例說(shuō)明
最近移植Android,當(dāng)Android能夠在設(shè)備上面運(yùn)行之后,首先想到的是讓音頻設(shè)備跑起來(lái)?!皼](méi)有聲音,再好的戲也出不來(lái)”接下來(lái)介紹Android音頻可視化開(kāi)發(fā)流程2012-12-12
Android實(shí)現(xiàn)動(dòng)態(tài)顯示或隱藏密碼輸入框的內(nèi)容
這篇文章主要介紹了Android實(shí)現(xiàn)動(dòng)態(tài)顯示或隱藏密碼輸入框的內(nèi)容,主要通過(guò)設(shè)置EditText的setTransformationMethod()方法來(lái)實(shí)現(xiàn),需要的朋友可以參考下2014-09-09
Android?鼠標(biāo)光標(biāo)的圖形合成原理實(shí)例探究
這篇文章主要為大家介紹了Android?鼠標(biāo)光標(biāo)的圖形合成原理實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01

