本文為大家分享了使用反射機(jī)制控制Toast顯示時(shí)間的具體代碼,供大家參考,具體內(nèi)容如下
1、Toast源碼分析:
Toast的默認(rèn)view是在transient_notification.xml中定義的一個(gè)TextView,如果需要設(shè)置Toast的界面,可以通過setView方法實(shí)現(xiàn);如果需要設(shè)置Toast默認(rèn)顯示的位置,可以通過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的顯示和消失。那么又是什么來完成調(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();}}可以看到該方法,通過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,那就沒有辦法實(shí)現(xiàn)了,因?yàn)楹问抡{(diào)用TN的hide方法,不是由你控制的。
下面通過Java的反射機(jī)制,拿到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();    }  }在外部,我們可以調(diào)用ReflectToast的show和cancel方法,來實(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í)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注