Android实例-手机安全卫士(四十三)-自由移动自定义Toast位置

一、目标

  实现自定义的Toast窗口在来电时可以自由移动至屏幕的任意位置,并保存该位置

二、代码实现 

  1、在“显示号码归属地”服务(ShowPhoneAddService)类中的自定义吐司(myToast)方法中,在窗口对象WindowManager.LayoutParams(params,该变量在后面的移动显示位置时需要用到,所以将其定义成服务类的成员变量)的便签(flag)属性里,需删除不可触摸属性(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE),在类型(type)属性里将其设置为具有电话优先级的类型( WindowManager.LayoutParams.TYPE_PRIORITY_PHONE,Toast类型对象在设计时就是不可触摸的),增加系统窗口弹出权限(SYSTEM_ALERT_WINDOW)(未增加该权限在运行时不会出现错误提示,只会出现权限被拒绝提示 permission denied for this window type); 

params中相关属性代码:

1 params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE// 将窗口标记为不获取焦点
2                 // 窗口不可触摸的标记为WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
3                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;// 将窗口标记为保持屏幕开启状态
4         params.format = PixelFormat.TRANSLUCENT;// 窗口样式为半透明
5         params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;// 窗口类型为具有电话优先级的类型
View Code

  2、通过View对象(view)的inflate()方法获取View对象后,通过View对象(View)的

setOnTouchListener(OnTouchListener l)方法为其设置触摸监听事件,参数OnTouchListener l通过new实例化OnTouchListener()对象监听器,并复写其中的onTouch(View v, MotionEvent event)方法,同时在OnTouchListener()中定义六个int类型的变量(取名startX,startY,newX,newY,dX,dY,分别作为手指触摸屏幕时的初始X轴坐标、Y轴坐标、移动后新的X轴坐标、新的Y轴坐标、X轴移动的距离、Y轴移动的距离)
  3、在复写的onTouch(View v, MotionEvent event)方法中,通过switch...case...语句判断事件的动作(event.getAction()),
    (1)当事件动作为手指按下屏幕时(MotionEvent.ACTION_DOWN),通过onTouch方法传入的移动事件MotionEvent对象(event)的getRawX()方法获取手指按下屏幕时Toast窗口的初始X轴坐标像素位置(注:此坐标轴的原点为屏幕左上角),同理获得Y轴的坐标;
    (2)当事件动作为手指在屏幕上移动时(MotionEvent.ACTION_MOVE),
      ①通过MotionEvent对象(event)的getRawX()、getRawY()方法获取Toast窗口新的X轴、Y轴坐标像素位置,获取新的坐标轴位置和起始坐标轴位置,并将其与Toast窗口的x轴、Y轴位置相加后再赋值给Toast窗口的X轴.Y轴;
      ②通过判断窗口对象WindowManager.LayoutParams(params)的x轴、Y轴坐标位置,若其小于零(即Toast窗口到达屏幕左边缘或上边缘),则将其设为0;若其大于屏幕宽度与Toast窗口宽度的差值(即Toast窗口到达右边缘或底边缘),则将其设为该差值;
      ③通过窗口管理对象(wm)的updateViewLayout(View view, LayoutParams params)方法更新Toast窗口显示位置,参数view为已加载的View对象(view),params为窗口对象WindowManager.LayoutParams(params);
      ④通过event的getRawX()、getRawY()方法重新获取Toast窗口的坐标并赋值给初始的X轴、Y轴坐标(startX、startY);
    (3)当事件动作为手指离开屏幕瞬间(MotionEvent.ACTION_UP)通过SharedPreferences对象(sp)的putInt()方法保存窗口对象WindowManager.LayoutParams(params)的x轴、y轴坐标。 
    (4)返回true,让父控件相应触摸事件;
为View对象设置触摸监听事件的代码:
 1 view.setOnTouchListener(new OnTouchListener() {
 2             int startX,startY,newX,newY,dX,dY;
 3                                 
 4             @Override
 5             public boolean onTouch(View v, MotionEvent event) {
 6                 switch (event.getAction()) {
 7                 case MotionEvent.ACTION_DOWN://手指触摸屏幕时
 8                     startX = (int) event.getRawX();//获取手指触摸屏幕时的初始X轴位置
 9                     startY = (int) event.getRawY();//获取手指触摸屏幕时的初始Y轴位置
10                     break;
11                 case MotionEvent.ACTION_MOVE://手指在屏幕上移动
12                     newX = (int) event.getRawX();
13                     newY = (int) event.getRawY();
14                     dX = newX - startX;
15                     dY = newY - startY;
16                     params.x += dX;
17                     params.y += dY;
18                     //边界,当Toast到达左边界时其X轴坐标为0,当到达右边界时其y轴为屏幕宽度减去Toast宽度。
19                     if(params.x<0){
20                         params.x = 0;
21                     }
22                     if(params.x>(wm.getDefaultDisplay().getWidth()-view.getWidth())){
23                         params.x = wm.getDefaultDisplay().getWidth()-view.getWidth();
24                     }
25                     if(params.y<0){
26                         params.y = 0;
27                     }
28                     if(params.y>(wm.getDefaultDisplay().getHeight()-view.getHeight())){
29                         params.y = wm.getDefaultDisplay().getHeight()-view.getHeight();
30                     }
31                     wm.updateViewLayout(view, params);//更新View对象布局
32                     startX = (int) event.getRawX();//重新初始化手指触摸屏幕时的初始X轴位置
33                     startY = (int) event.getRawY();//重新初始化手指触摸屏幕时的初始Y轴位置
34                     break;
35                 case MotionEvent.ACTION_UP://手指离开屏幕瞬间
36                     //保存Toast的位置,再下次来电时根据上次移动的位置显示
37                     Editor editor = sp.edit();
38                     editor.putInt("ToastX", params.x);
39                     editor.putInt("ToastY", params.y);
40                     editor.commit();
41                     break;
42                 }
43                 return false;
44             }
45         });
View Code

   4、在设置Toast窗口显示位置(params.x、params.y)时,通过SharedPreferences对象(sp)的getInt()方法获取已经保存的显示位置。

从配置文件中获取已保存的显示位置代码;

1         params.x = sp.getInt("ToastX", 0);// 设置Toast窗口左边缘距屏幕窗口左边界的偏移量为50像素
2         params.y = sp.getInt("ToastY", 0);// 设置Toast窗口上边缘距屏幕窗口顶边界的偏移量为50像素
View Code

 

 

posted @ 2015-05-06 16:13  红烧大白鲨  阅读(303)  评论(0编辑  收藏  举报