一个可以自由移动的土司
1、就是给Toast注册一个触摸事件 2、由于是Toast,且配置了params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE// 不可触摸 3、params.type = WindowManager.LayoutParams.TYPE_TOAST;// 类型,本身就不可以被移动 所以要改类型: public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7;//低级模拟器接电话,那两个接通和挂断的按钮,可以移动,位于所有窗体之上,所以需要权限。 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 4、更新界面时,不要layout(),而是用WindowManager中的updateViewLayout()来更新移动的位置 params.x += dX;
params.y += dY;
windowManager.updateViewLayout(view_toast, params);
// params。toast在窗体上的参数5、将移动后的位置,保存起来,下次还是在这个位置 case MotionEvent.ACTION_UP:
Log.i(TAG, "toast弹起了。。。");
// 拨打电话时Toast移动后,记住移动后的位置,下次还是在这个位置。
// TODO 记录最后的距离屏幕左边 和 上边位置 存到sp里面,这里获取不到值,这样可以
params.gravity = Gravity.LEFT + Gravity.TOP;
int left = params.x;
int top = params.y;
// int left = view_toast.getLeft();//这是获取不到值的
// int top = view_toast.getTop();//这是获取不到值的
Editor edit = sp.edit();
edit.putInt("left", left);
edit.putInt("top", top);
edit.commit();
break;
|
核心代码: /**
* 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);*/
view_toast = View.inflate(getApplicationContext(), R.layout.toast_info,null);
int toastWhich = sp.getInt("toastWhich", 0);//选择的是哪一个边框样式
view_toast.setBackgroundResource(bgs[toastWhich]);
TextView tv_toast_info = (TextView) view_toast.findViewById(R.id.tv_toast_info);
tv_toast_info.setText(phoneAddress);
// d)为土司设置触摸事件,可以移动的土司
view_toast.setOnTouchListener(new OnTouchListener() {
private int startX;// toast触摸的起始x
private int startY;// toast触摸的起始y
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "toast被按下了。。。");
// 1)获取起始位置
startX = (int) event.getRawX();
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "toast移动了。。。");
// 2)移动时,获取当前x和y的位置
int newX = (int) event.getRawX();
int newY = (int) event.getRawY();
// 3)当前移动到的位置和起始点的距离
int dX = newX - startX;
int dY = newY - startY;
// 4)更新toast的在界面的位置
params.x += dX;
params.y += dY;
windowManager.updateViewLayout(view_toast, params);// params。toast在窗体上的参数
// 5)重新更新起始位置
startX = (int) event.getRawX();
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "toast弹起了。。。");
// FIXME 移动后,记住移动后的位置,下次还是在这个位置。
break;
}
return true;
}
});
// c)
params = new WindowManager.LayoutParams();
// 设置拨打电话提示框显示的位置,根据之前设置的位置来显示
params.gravity = Gravity.LEFT + Gravity.TOP;// 默认是Gravity.CENTER
params.x = sp.getInt("left", 0);// 要和上面的Gravity.LEFT等一起使用,否则,会被忽略掉
params.y = sp.getInt("top", 0);
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;//类型,要想触摸移动,要下面的类型
params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
windowManager.addView(view_toast, params);
}
|
|