您好,登錄后才能下訂單哦!
這篇文章主要介紹了如何使用反射機(jī)制控制Toast的顯示時(shí)間,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
具體內(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; } } }); } }
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“如何使用反射機(jī)制控制Toast的顯示時(shí)間”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。