溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用反射機(jī)制控制Toast的顯示時(shí)間

發(fā)布時(shí)間:2021-06-28 10:16:36 來(lái)源:億速云 閱讀:173 作者:小新 欄目:移動(dòng)開(kāi)發(fā)

這篇文章主要介紹了如何使用反射機(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í)!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI