本文為大家分享了使用反射機制控制Toast顯示時間的具體代碼,供大家參考,具體內容如下
1、Toast源碼分析:
Toast的默認view是在transient_notification.xml中定義的一個TextView,如果需要設置Toast的界面,可以通過setView方法實現;如果需要設置Toast默認顯示的位置,可以通過setGravity或者setMargin方法進行設置,值得一提的是setMargin方法的參數范圍是0-1即它是屏幕的百分比,如setMargin(0.1,0.1)。
Toast 的構造函數,會實例化TN對象,TN對象擁有show和hide兩個方法,可以控制Toast的顯示和消失。那么又是什么來完成調用和何時調用這兩個方法的呢?我們可以從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 } }該方法,首先會判斷待顯示的view對象是否為null;然后獲取單例的INotificationManager的對象,最后把當前Toast的請求加入到顯示隊列,同時把該Toast需要顯示的時間也傳了進去。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();}}可以看到該方法,通過transact方法調用了底層代碼,即使用了binder的機制。service最終根據duration,調用TN的show和hide方法顯示和隱藏Toast界面。
2、如何修改Toast的顯示時間
Toast默認有兩種顯示時間,分別是LENGTH_SHORT和LENGTH_LONG。如果我們需要Toast顯示的時間,小于LENGTH_SHORT,那么非常容易實現,直接調用Toast的cancel方法即可。那么我們如果想Toast的顯示時間大于LENGTH_LONG,那就沒有辦法實現了,因為何事調用TN的hide方法,不是由你控制的。
下面通過Java的反射機制,拿到TN的show和hide方法,自己來控制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(); } }在外部,我們可以調用ReflectToast的show和cancel方法,來實現控制Toast的顯示和隱藏。
為了不讓大家再出錯,給出調用代碼如下:
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; } } }); }}以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
新聞熱點
疑難解答