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;// 窗口类型为具有电话优先级的类型

  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         });

  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像素

时间: 2024-11-08 19:44:49

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

Android实例-手机安全卫士(十)-自定义对话框

一.目标. 当点击“手机防盗”时弹出自定义的设置密码对话框.如果已经设置密码,则弹出自定义的输入密码对话框. 二.代码实现. 1.在layout文件夹下新建xml(取名setpwddialog.xml)文件用于设置自定义对话框的UI. 新建xml文件代码如下; 1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.a

Android实例-手机安全卫士(七)-自定义组合控件

一.目标. 将多个系统控件(TextView.Button.CheckBox等)组合成一个自定义的控件,并像系统控件一样使用.如图所示第1个自动更新控件是根据相对布局放置而成的,第2个自动更新控件即为自定义组合控件,它可以想一般的TextView等系统控件一样重复使用. 自定义控件如图: 二.代码实现. 1.在layout文件夹下新建一个xml文件(取名model_setting_item.xml),用于保存自定义控件的布局. 2.在新建的xml文件(model_setting_item.xml

Android实例-手机安全卫士(十一)-自定义对话框点击事件处理

一.目标 在弹出的自定义对话框中,当点击“确认”时,保存密码,关闭对话框:当点击“取消”时关闭对话框.同时,如果不输入密码或输入密码错误则弹出相应的提示. 二.代码实现. 1.在主界面代码类(HomeActivity)中定义设置防盗密码对话框中的对应TextView.Button等成员变量,并在显示设置防盗密码对话框方法(showSetPwdDialog)中通过view.findViewById方法找到对应的组件: 2.为“取消”按钮设置取消操作的监听事件并进行处理.通过setOnClickLi

Android实例-手机安全卫士(九)-自定义组合控件的属性

一.目标. 在布局文件中使用自定义控件时,直接在属性中设置值,类似于在TextView控件中设置text属性来显示文本. 效果如图:      属性设置: 二.代码实现. 1.自定义命名空间,类似于TextView控件里面android:text属性前的android.在需要放置自定义控件的布局文件的布局方式(LinearLayout.RelativeLayout等均可)属性里,参照android的命名空间样式增加自定义的命名空间,其名称可以随便取(本例中取名custom),代码是:xmlns:

Android实例-手机安全卫士(十七)-自定义按钮背景样式

一.目标. 按钮(button)默认.按下.获取焦点等状态下,其背景均显示自定的图片.            二.代码实现. 1.在res文件夹下新建drawable文件夹,在新建的drawable文件夹下新建一个文件(右键-new-file),取名button.xml. 2.在新建的文件(button.xml)中 ①.指定xml版本为1.0,编码格式为utf-8(即第一行为:<?xml version="1.0" encoding="utf-8"?>)

Android实例-手机安全卫士(八)-自定义组合控件事件相应和改变状态

一.目标. 实现自定义控件点击事件响应和内容状态变化. 1.点击自定义控件内的任何区域时,CheckBox状态均会变化. 2.自定义控件里面的内容会根据CheckBox的状态进行改变. 效果图1:      二.代码实现. 1.在自定义控件类(SettingItemView)中增加方法. ①.在自定义控件类对应的xml文件(SettingItemView)中设置各个控件的id,便于自定义控件类(SettingItemView)对它们进行操作.同时,设置CheckBox的clickable属性为f

Android实例-手机安全卫士(四十二)-设置自定义Toast位置

一.目标 设置自定义Toast窗口的显示位置(第1-2步): 二.代码实现 1.在“显示号码归属地”服务(ShowPhoneAddService)类中的自定义吐司(myToast)方法中,通过窗口对象WindowManager.LayoutParams(params)的gravity属性可设置自定义Toast的对齐方式(顶部:Gravity.TOP,左上角:Gravity.TOP+Gravity.LEFT): 2.通过窗口对象WindowManager.LayoutParams(params)的

Android实例-手机安全卫士(四十)-自定义吐司(二)(布局样式、背景)

一. 自定义Toast的布局.背景等 二.代码实现 1.在res文件夹下的layout文件夹中新建布局文件(Android xml file,取名phone_add_toast),用于定义要显示的Toast的布局方式: 2.根据设计要求自定义的Toast布局为左右的水平线性布局,宽高均为包裹内容,左边为图片,右边为归属地信息文本(由于归属地信息会根据号码不同而改变,因此可为其设置id(tv_phone_add_toast)): (1)图片采用<ImageView>组件,通过android:sr

Android实例-手机安全卫士(十八)-完成设置向导的4个UI和跳转事件

一.目标. 制作向导设置里面每一步的UI布局及点击事件控制. 1.使用自定义button背景.自定义组合控件.自定义文本样式等. 2.利用SharedPreferences对象,设置应用程序配置信息(向导设置完成后就不再进入)           二.代码实现. 1.在程序包下新建另外3个UI的类(分别为SetupWizard_ui_2.java.SetupWizard_ui_3.java.SetupWizard_ui_4.java),并在配置文件中注册Activity. 2.根据UI设计,在设

Android实例-手机安全卫士(三)-设计主页面UI

一.目标. 主界面UI如图所示: 方面是一个功能列表提示框(采用TextView),下面是功能列表(采用GridView). 二.代码实现. 1.在主界面布局文件(activity_home.xml)中增加组件.主界面布局文件(activity_home.xml)采用线性布局,上面一个TextView,根据UI设置相应属性:下面一个是GridView,通过android:numColumns属性设置该组件的列数,由于GridView还需要inflate单个布局文件,所以为其设置id. 主界面布局