Custom Toast Principle
Profile
1. Problems with Toast
2. Toast Source and principle
3. My Singleton class T.java
Issues that you encounter with toast
- A native toast is really hard to see, isn't it?
Multiple toasts are displayed in turn, the program is over and it's still showing.
Workaround: Customize Toast + Singleton class
Toast Source and principle
Toast is not a lot of source code, only 423 lines
Some of the methods we use often do not need to say much, for example:
public Toast(Context context)
public void show()
public void cancel()
public static Toast makeText(Context context, int resId, int duration)
public static Toast makeText(Context context, CharSequence text, int duration)
It is important to:
There is an inner class TN
(actually a binder) that is TransientNotification
the abbreviation短暂的通知
Private Static class TN extends itransientnotification. Stub { FinalRunnable mshow =NewRunnable () { Public void Run() {handleshow (); } };FinalRunnable mhide =NewRunnable () { Public void Run() {handlehide ();//Don ' t do this in handlehide () because it's also invoked by Handleshow ()Mnextview =NULL; } };Private FinalWindowmanager.layoutparams Mparams =NewWindowmanager.layoutparams ();FinalHandler Mhandler =NewHandler ();intmgravity = Gravity.center_horizontal | Gravity.bottom;intMX, MY;floatMhorizontalmargin;floatMverticalmargin;/** * @me: Mnextview is a toast to display the view */View MView; View Mnextview; Windowmanagerimpl MWM;/** * @me: Here are some notable params.flags * make it non-clickable, no focus, guaranteed screen highlight * window type is WINDOWMANAGER.LAYOUTP Arams. Type_toast * *TN () {//XXX This should is changed to use a Dialog, with a theme.toast //defined that sets up the layout params appropriately. FinalWindowmanager.layoutparams params = Mparams; Params.height = WindowManager.LayoutParams.WRAP_CONTENT; Params.width = WindowManager.LayoutParams.WRAP_CONTENT; Params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; Params.format = pixelformat.translucent; Params.windowanimations = Com.android.internal.r.style.animation_toast; Params.type = WindowManager.LayoutParams.TYPE_TOAST; Params.settitle ("Toast"); }/** * Schedule handleshow into the right thread * * Public void Show() {if(LOCALLOGV) LOG.V (TAG,"SHOW:"+ This); Mhandler.post (mshow); }/** * Schedule handlehide into the right thread * * Public void Hide() {if(LOCALLOGV) LOG.V (TAG,"HIDE:"+ This); Mhandler.post (Mhide); } Public void Handleshow() {if(LOCALLOGV) LOG.V (TAG,"HANDLE SHOW:"+ This+"mview="+ MView +"mnextview="+ Mnextview);if(MView! = Mnextview) {//Remove the old view if necessaryHandlehide (); MView = Mnextview; MWM = Windowmanagerimpl.getdefault ();Final intGravity = mgravity; Mparams.gravity = Gravity;if((Gravity & gravity.horizontal_gravity_mask) = = gravity.fill_horizontal) {mparams.horizontalweight =1.0F }if((Gravity & gravity.vertical_gravity_mask) = = gravity.fill_vertical) {mparams.verticalweight =1.0F } mparams.x = MX; Mparams.y = MY; Mparams.verticalmargin = Mverticalmargin; Mparams.horizontalmargin = Mhorizontalmargin;if(Mview.getparent ()! =NULL) {if(LOCALLOGV) LOG.V (TAG,"remove!"+ MView +"in"+ This); Mwm.removeview (MView); }if(LOCALLOGV) LOG.V (TAG,"add!"+ MView +"in"+ This); Mwm.addview (MView, mparams); Trysendaccessibilityevent (); } }Private void trysendaccessibilityevent() {Accessibilitymanager Accessibilitymanager = accessibilitymanager.getinstance (mview.getc Ontext ());if(!accessibilitymanager.isenabled ()) {return; }//Treat toasts as notifications since they is used to //announce a transient piece of information to the userAccessibilityevent event = Accessibilityevent.obtain (accessibilityevent.type_notification_state_change D); Event.setclassname (GetClass (). GetName ()); Event.setpackagename (Mview.getcontext (). Getpackagename ()); Mview.dispatchpopulateaccessibilityevent (event); Accessibilitymanager.sendaccessibilityevent (event); } Public void Handlehide() {if(LOCALLOGV) LOG.V (TAG,"HANDLE HIDE:"+ This+"mview="+ MView);if(MView! =NULL) {//note:checking parent () just to make sure the view have //Been added ... I have a seen cases where we get here //The view isn ' t yet added, so let's try not to crash. if(Mview.getparent ()! =NULL) {if(LOCALLOGV) LOG.V (TAG,"remove!"+ MView +"in"+ This); Mwm.removeview (MView); } MView =NULL; } } }
and here's what's important:
The Mservice call in the toast is actually called through the IPC to the Notificationmanagerservice
privatestatic INotificationManager sService; staticprivategetService() { ifnull) { return sService; } sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification")); return sService; }
In the key Toast Show () method:
public void show () {if (Mnextview = null ) {throw new Ru Ntimeexception ( "Setview must has been called" ); } Inotificationmanager service = GetService (); String pkg = Mcontext.getpackagename (); TN tn = MTN; Tn.mnextview = Mnextview; try {Service.enqueuetoast (pkg, TN, mduration); } catch (remoteexception e) {//Empty } }
INotificationManager
Give the message Notification
to the processing Toast
display, the message is all placed in a set,
It's so defined. private ArrayList<ToastRecord> mToastQueue;
This is why multiple Toast
displays are displayed one at a time until there is no message.
My Singleton class T.java
To give an example of a custom toast:
Layoutinflater inflater = Getlayoutinflater ();View layout = Inflater. Inflate(R. Layout. Custom, (ViewGroup) Findviewbyid (R. ID. Lltoast));ImageView image = (ImageView) layout. Findviewbyid(R. ID. Tvimagetoast);Image. Setimageresource(R. drawable. Icon);TextView title = (TextView) layout. Findviewbyid(R. ID. Tvtitletoast);Title. SetText("Attention");TextView Text = (TextView) layout. Findviewbyid(R. ID. Tvtexttoast);Text. SetText("Custom Toast");Toast = new Toast (Getapplicationcontext ());Toast. Setgravity(Gravity. Right| Gravity. TOP, A, +);Toast. Setduration(Toast. LENGTH_long);Toast. Setview(layout);Toast. Show();
You can do this, but I'm not going to do this.
A tool class is a standalone entity that minimizes reliance on other resources
So I use the code layout here to build the interface
/** * Toast Tool Class * * Singleton class * * Public class T { Private StaticToast toast =NULL;Private StaticLinearLayout Toastview =NULL;Private Static Final intTextid =2345;/** * Toast.length_long * * Public Static void L(String msg) {Createtoast (Lianapplication.getinstance ()); Toast.setduration (Toast.length_long); SetText (msg); Toast.show (); }/** * Toast.length_short * * Public Static void s(String msg) {Createtoast (Lianapplication.getinstance ()); Toast.setduration (Toast.length_short); SetText (msg); Toast.show (); }Private Static void SetText(String msg) {TextView TV = (TextView) Toastview.findviewbyid (Textid);if(TV! =NULL) {Tv.settext (msg); } }Private Static void Createtoast(Context context) {if(Toastview = =NULL) {Toastview =NewLinearLayout (context); Toastview.setorientation (linearlayout.vertical); Linearlayout.layoutparams Layoutparams =NewLinearlayout.layoutparams (LinearLayout.LayoutParams.WRAP_CONTENT, Linearlayout.layo Utparams.wrap_content); Toastview.setlayoutparams (Layoutparams); Toastview.setbackgroundcolor (Color.gray); TextView TextView =NewTextView (context); Textview.settext (""); Textview.setpadding (Ten,Ten,Ten,Ten); Textview.settextcolor (Color.White); Textview.setlayoutparams (Layoutparams);//Note Set IDTextview.setid (Textid); Toastview.addview (TextView); }if(Toast = =NULL) {toast =NewToast (context); Toast.setgravity (Gravity.center,0,0); Toast.setview (Toastview); } }}
Android principle--Custom toast principle