Toast显示的时间最长是5S,有时候需要显示的时间更长;Toast默认背景是黑色的,有时候希望它更炫酷;所以,你需要自定义Toast。
那么,怎么去自定义呢?找到系统Toast源代码抽出来,依葫芦画瓢!分两步:
1.获取Toast的对象:获取toast里面需要填充的view对象
2.显示toast:设置一些显示的参数,获取一个窗口管理器,将该view加入到该窗口上
通常Toast.makeText(Context context, CharSequence text, int duration).show一步搞定。那先来看看makeTest()方法中是些什么。
1 public static Toast makeText(Context context, CharSequence text, int duration) { 2 Toast result = new Toast(context); 3 4 LayoutInflater inflate = (LayoutInflater) 5 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 6 View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null); 7 TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message); 8 tv.setText(text); 9 10 result.mNextView = v; 11 result.mDuration = duration; 12 13 return result; 14 }
可以看到黄色标注的填充了一个系统的布局文件,换成自己定义的布局文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 android:background="@drawable/call_locate_gray"> 7 8 <TextView 9 android:id="@+id/tv_mytoast_addr" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:layout_gravity="center_horizontal" 13 android:textColor="#000000" 14 android:drawableLeft="@android:drawable/stat_sys_phone_call" 15 android:shadowColor="#BB000000" 16 android:shadowRadius="2.75" 17 /> 18 19 </LinearLayout>
再来看看这个TN构造函数:
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
1 TN() { 2 // XXX This should be changed to use a Dialog, with a Theme.Toast 3 // defined that sets up the layout params appropriately. 4 final WindowManager.LayoutParams params = mParams; 5 params.height = WindowManager.LayoutParams.WRAP_CONTENT; 6 params.width = WindowManager.LayoutParams.WRAP_CONTENT; 7 params.format = PixelFormat.TRANSLUCENT; 8 params.windowAnimations = com.android.internal.R.style.Animation_Toast;//自定义时删除 9 params.type = WindowManager.LayoutParams.TYPE_TOAST; 10 params.setTitle("Toast"); 11 params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 12 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 13 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 14 }
源代码中有showMyToast()和hideMyToast()两个方法后,可以任意显示和关闭
private WindowManager mWM;
private View v;
1 private void showMyToast(String addr) { 2 //初始化view 3 LayoutInflater inflate = (LayoutInflater) 4 getSystemService(Context.LAYOUT_INFLATER_SERVICE); 5 v = inflate.inflate(R.layout.mytoast_showaddr, null); 6 TextView tv = (TextView)v.findViewById(R.id.tv_mytoast_addr); 7 tv.setText(addr); 8 9 10 11 //private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); 12 13 final WindowManager.LayoutParams params = new WindowManager.LayoutParams();; 14 params.height = WindowManager.LayoutParams.WRAP_CONTENT; 15 params.width = WindowManager.LayoutParams.WRAP_CONTENT; 16 params.format = PixelFormat.TRANSLUCENT; 17 //params.windowAnimations = com.android.internal.R.style.Animation_Toast; 18 params.type = WindowManager.LayoutParams.TYPE_TOAST; 19 params.setTitle("Toast"); 20 params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 21 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 22 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 23 24 mWM = (WindowManager)getSystemService(Context.WINDOW_SERVICE);//获取窗口管理器并加入该view 25 mWM.addView(v, params); 26 27 }
1 private void hideMyToast(){ 2 3 if (v!=null) { 4 mWM.removeView(v); 5 } 6 v=null; 7 }
效果图:本例是模仿手机管家中来电开启显示号码归属地功能。当来电时显示使用toast显示归属地,去电时toast消失。
源代码:
1 package com.cskaoyan.mobilemanager.service; 2 3 import com.cskaoyan.mobilemanager.R; 4 import com.cskaoyan.mobilemanager.dao.AdressQueryDao; 5 6 import android.app.Service; 7 import android.content.Context; 8 import android.content.Intent; 9 import android.graphics.PixelFormat; 10 import android.os.IBinder; 11 import android.telephony.PhoneStateListener; 12 import android.telephony.TelephonyManager; 13 import android.view.LayoutInflater; 14 import android.view.View; 15 import android.view.WindowManager; 16 import android.widget.TextView; 17 import android.widget.Toast; 18 19 public class ShowCallLocation extends Service { 20 21 private TextView tv; 22 private WindowManager mWM; 23 private View v; 24 private TelephonyManager tm; 25 private MyPhoneCallListener listener; 26 27 @Override 28 public IBinder onBind(Intent intent) { 29 // TODO Auto-generated method stub 30 return null; 31 } 32 33 @Override 34 public int onStartCommand(Intent intent, int flags, int startId) { 35 tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); 36 listener = new MyPhoneCallListener(); 37 tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); 38 39 System.out.println("ShowCallLocation.onStartCommand()"); 40 return super.onStartCommand(intent, flags, startId); 41 } 42 43 class MyPhoneCallListener extends PhoneStateListener{ 44 45 @Override 46 public void onCallStateChanged(int state, String incomingNumber) { 47 // TODO Auto-generated method stub 48 49 switch (state) { 50 case TelephonyManager.CALL_STATE_IDLE: 51 hideMyToast(); 52 break; 53 case TelephonyManager.CALL_STATE_RINGING: 54 String addr = AdressQueryDao.querryAddr(incomingNumber);//取出来电查询到的号码归属地 55 System.out 56 .println("ShowCallLocation.MyPhoneCallListener.onCallStateChanged()"+addr); 57 Toast.makeText(getApplicationContext(), addr, 1).show(); 58 59 //显示一个自定义的toast 60 showMyToast(addr); 61 break; 62 case TelephonyManager.CALL_STATE_OFFHOOK: 63 64 break; 65 66 67 68 default: 69 break; 70 } 71 super.onCallStateChanged(state, incomingNumber); 72 } 73 74 75 76 } 77 78 /* 79 * 1.获取Toast的对象——:获取toast里面需要填充的view对象 80 * 2.显示toast:设置一些显示的参数,获取一个窗口管理器,将该view加入到该窗口上 81 * */ 82 private void showMyToast(String addr) { 83 //初始化view 84 LayoutInflater inflate = (LayoutInflater) 85 getSystemService(Context.LAYOUT_INFLATER_SERVICE); 86 v = inflate.inflate(R.layout.mytoast_showaddr, null); 87 TextView tv = (TextView)v.findViewById(R.id.tv_mytoast_addr); 88 tv.setText(addr); 89 90 91 92 //private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); 93 94 final WindowManager.LayoutParams params = new WindowManager.LayoutParams();; 95 params.height = WindowManager.LayoutParams.WRAP_CONTENT; 96 params.width = WindowManager.LayoutParams.WRAP_CONTENT; 97 params.format = PixelFormat.TRANSLUCENT; 98 //params.windowAnimations = com.android.internal.R.style.Animation_Toast; 99 params.type = WindowManager.LayoutParams.TYPE_TOAST; 100 params.setTitle("Toast"); 101 params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 102 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 103 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 104 105 mWM = (WindowManager)getSystemService(Context.WINDOW_SERVICE); 106 mWM.addView(v, params); 107 108 } 109 110 private void hideMyToast(){ 111 112 if (v!=null) { 113 mWM.removeView(v); 114 } 115 v=null; 116 } 117 118 @Override 119 public void onDestroy() { 120 // TODO Auto-generated method stub 121 tm.listen(listener, PhoneStateListener.LISTEN_NONE); 122 123 if (tm!=null) { 124 tm=null; 125 } 126 if (listener!=null) { 127 listener=null; 128 } 129 super.onDestroy(); 130 System.out.println("ShowCallLocation.onDestroy()"); 131 } 132 133 134 }