自定义Toast
一、查看Toast的源码1、系统Toast背景:toast_frame.9.png 2、Toast显示在window上 mWM = WindowManagerImpl.getDefault(); ... mWM.addView(mView, mParams); Toast.java public void handleShow() {
if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+ " mNextView=" + mNextView);
if (mView != mNextView) {
// remove the old view if necessary
handleHide(); //显示之前,要将前面的给隐藏掉
mView = mNextView;
mWM = WindowManagerImpl.getDefault();
final int gravity = 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();
}
}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 has
// been added... i have seen cases where we get here when
// 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;
}
}3、Toast就是将一个自定义的View对象加载到窗体上 |
注意:所有在代码中的单位都是像素pixel |
二、自定义Toast 步骤: 1)从系统源码Toasth中我们可以看到,Toast原理就是将一个自定义的View对象显示到界面上 2)然后在显示Toast的地方,自定义自己定义的View到界面上 3)为了Toast好看,我们需要自定义一个View对象-自定义布局修改默认的Toast, 4)将该自定义的布局转成view对象,设置该布局到Toast, 5)参考金山卫士的归属地显示风格 |
1、代码创建显示Toast的TextView对象 a) 代码创建 /**
* 3、弹出自定义的土司
* @param phoneAddress 要弹出的土司
*/
public void toastAddress(String phoneAddress) {
//a) 得到窗体管理者
windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
// b) 设置要显示的view
tv_toast = new TextView(getApplicationContext());
tv_toast.setText(phoneAddress);
tv_toast.setTextSize(20);
tv_toast.setTextColor(Color.RED);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();;
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.type = WindowManager.LayoutParams.TYPE_TOAST;// 类型
windowManager.addView(tv_toast, params);
}b)在电话处于空闲的状态时,移除该窗体的TextView对象 case TelephonyManager.CALL_STATE_IDLE:// 电话空闲,也就是电话挂断了,或者没接通
if (windowManager != null) {
windowManager.removeView(tv_toast);// 在电话空闲的时候,将土司显示到窗体的内容给移除掉
}
break;
}
|
2、使用xml布局文件来自定义toast显示的界面 和1中,使用代码创建一致,只是用一个布局文件而已 toast_info.xml <?xml version="1.0" encoding="utf-8"?>
<!-- 18、土司弹出来的自定义界面 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/call_locate_green"
android:gravity="center"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/toast_image"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/tv_toast_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/phone_locale"
android:textColor="#ffffff"
android:textSize="20sp" />
</LinearLayout> 结果: |
问题1: Toast显示在所有的窗体上,不会消失,但第二次有电话拨打进来,又会在窗体上显示 应用场景:一键锁屏,在每一个窗体上都有一个图标,其实是一个。 |
问题2: 多个电话拨打进来的时候,后面的会将前面的覆盖掉 a) 用一个List集合保存 b) showAddress()返回该View |