自定义View
- 自定义Toast
01-自定义Toast
- 需求 : 自定义Toast,并可任意拖动.
- 实现 :
- 通过分析Toast源码可以得出以下结论
- Toast的显示是通过WindowManager的addView方法实现的
- Toast的隐藏是通过WindowManager的removeView方法实现的
- 如果希望Toast可触摸被拖动
- 去掉WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 属性
- 更改类型为WindowManager.LayoutParams.TYPE_PRIORITY_PHONE.
- 为该视图添加OnTouchListener, 并实现对应的触摸事件
- 使用WindowManager.LayoutParams.TYPE_PRIORITY_PHONE类型, 需要添加权限
- 视图的更新使用WindowManager的updateViewLayout方法实现
- Toast的隐藏在PhoneStateListener中TelephonyManager.CALL_STATE_IDLE状态下实现
- 通过分析Toast源码可以得出以下结论
代码:
public class LocationToast implements OnTouchListener { private WindowManager mWM; private Context context; private View mView; private WindowManager.LayoutParams params = new WindowManager.LayoutParams(); private float startX; private float startY; public LocationToast(Context context) { this.context = context; // 初始化WindowManager mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); // 初始化LayoutParams params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT;// 图片显示的格式 params.type = WindowManager.LayoutParams.TYPE_TOAST;// 设置窗体的类型 params.setTitle("Toast"); // 添加到WindowManager后如何显示 params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON // 屏幕常亮 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 禁止获取焦点 } // 显示Toast public void show(String msg) { if (mView == null) { mView = View.inflate(context, R.layout.location_toast, null); mView.setOnTouchListener(this); } // 获取界面上的TextView, 并设置文本 TextView tView = (TextView) mView.findViewById(R.id.act_location_tv_location); tView.setText(msg); // 显示Toast if (mView.getParent() != null) { mWM.removeView(mView); } mWM.addView(mView, params); } // 隐藏Toast public void hide() { if (mView != null) { if (mView.getParent() != null) { mWM.removeView(mView); } mView = null; } } // 拖动事件 @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); // 手指按下时获取坐标点 if (action == MotionEvent.ACTION_DOWN) { startX = event.getRawX(); startY = event.getRawY(); } else if (action == MotionEvent.ACTION_MOVE) { // 手指移动时获取坐标点 float currentX = event.getRawX(); float currentY = event.getRawY(); // 获取偏移量 float movedX = currentX - startX; float movedY = currentY - startY; // 让View根据偏移量移动 params.x += (int) movedX; params.y += (int) movedY; mWM.updateViewLayout(mView, params); // 重置坐标点 startX = currentX; startY = currentY; } return false; } }