The reason why the Toast message prompt box is automatically closed after a certain period of time is displayed is that there is a Toast queue in the system. The system extracts (out queue) a Toast from the queue in sequence and displays it. After a period of time is displayed, close it and then display the next Toast message prompt box. Until all the Toast messages in the Toast queue are displayed. Sometimes this Toast prompt box needs to be displayed for a long time until it needs to be closed through code instead of automatically disabling the Toast prompt box. However, this requirement is too much for Toast itself, because the Toast class does not provide this function. Despite this, there are always more methods than problems. It is not complicated to implement this function through some special processing.
You can see from section 7.3.1 that the Toast information prompt box needs to call the Toast. show Method for display. Next let's take a look at the source code of the show method.Copy codeThe Code is as follows: publicvoidshow (){
If (mNextView = null ){
ThrownewRuntimeException ("setViewmusthavebeencalled ");
}
Inotifmanagmanagerservice = getService ();
Stringpkg = mContext. getPackageName ();
TNtn = mTN;
Try {
// Add the current Toast to the Toast queue
Service. enqueueToast (pkg, tn, mDuration );
} Catch (remoteeffectione ){
// Empty
}
}
The code of the show method is not complex. You can easily find the following code.Copy codeThe Code is as follows: service. enqueueToast (pkg, tn, mDuration );
The code above can easily infer that its function is to add the current Toast to the system's Toast queue. Readers should think of it here. Although the show method displays the Toast information prompt box, the actual function is to add Toast to the queue, and then the system displays the Toast information prompt Box Based on the Toast queue. After further consideration, we can boldly make a preliminary solution. Since the system's Toast queue can display the Toast information prompt box, why cannot we display it on our own? In this case, you can control the display and closure of the Toast information prompt box! Of course, you can no longer call the show method to display the Toast information prompt box (because the show method will add Toast to the queue, so that we cannot control Toast ).
Now that the preliminary scheme has been developed, implement it. Find out whether there are other show methods in the Toast class. The result shows a TN class, which is an embedded class of Toast. There is a show method in the TN class. TN is a subclass of ITransientNotification. Stub. The show method in ITransientNotification and TN class is preliminarily inferred (because the Chinese meaning of Transient is "short") after the system obtains the Toast object from the Toast queue, display Toast using the show method of TN object, and then use TN. use the hide method to disable Toast. First, we declare that this is just a hypothesis. We do not know whether this is feasible! Of course, this is also a general method of scientific research, first to deduce or assume, and then to prove the inference or hypothesis.
Now the key step is to get the TN object. Unfortunately, TN is declared as private and cannot be accessed from outside. But don't worry. There is an mTN variable in the Toast class. Although it is not a public variable, it can still be accessed through reflection technology. The mTN variable is initialized when the Toast object is created. Therefore, as long as the mTN variable is obtained, the TN object is obtained. The following code displays a Toast information prompt box that will never be automatically closed.Copy codeThe Code is as follows: // create a Toast object first
Toasttoast = Toast. makeText (this, "never disappear Toast", Toast. LENGTH_SHORT );
// Set the position of the Toast prompt box (horizontally centered at the top of the screen)
Toast. setGravity (Gravity. TOP | Gravity. CENTER_HORIZONTAL, 0, 0 );
Try
{
// Obtain the mTN variable from the Toast object
Fieldfield = toast. getClass (). getDeclaredField ("mTN ");
Field. setAccessible (true );
Objectobj = field. get (toast );
// The show method is obtained in the TN object.
Methodmethod = obj. getClass (). getDeclaredMethod ("show", null );
// Call the show method to display the Toast information prompt box
Method. invoke (obj, null );
}
Catch (effectione)
{
}
In the above Code, try {...} Catch (...) {...} The code in the statement is the key. The mTN variable is obtained by using the previously created Toast object. Then, we use the reflection technology to obtain the show method of TN objects.
The method for disabling Toast is similar to that for displaying Toast. You only need to obtain the hide method. The Code is as follows:Copy codeThe Code is as follows: try
{
// Convert the obj variable in the previous code into a class variable. In this way, access is available in multiple places.
Methodmethod = obj. getClass (). getDeclaredMethod ("hide", null );
Method. invoke (obj, null );
}
Catch (effectione)
{
}
The above code has perfectly implemented the function of displaying and disabling the Toast information prompt box through code control. If you want to achieve perfection, you can find an ITransientNotification in the AndroidSDK source code. aidl file (this file is the AIDL service definition file, which will be detailed later), and create an Android in the src directory of the android project. app package, put this file in this package. Then, the ADT automatically generates an android. app package in the gen Directory, which contains an ITransientNotification. java file. Because the ItransientNotification interface provided by AndroidSDK is an internal resource and cannot be accessed by external programs, you can only convert the mTN variable obtained from the Toast object to the generated ITransientNotification object. In this way, the reflection technology does not need to obtain the show and hide methods. The improved code for displaying and disabling the Toast prompt box is as follows:Copy codeThe Code is as follows: ITransientNotificationnotification = (ITransientNotification) field. get (toast );
// Display the Toast prompt box
Notification. show ();
// Close the Toast prompt box
Notification. hide ();