android 实现自由移动的悬浮按钮

实现原理
主要是通过android中的WindowManager中的addview()把view加载进来,设置WindowManager.LayoutParams windowManagerParams的相关属性,例如x,y;在view的onTouchEvent中改变x,y从而实现悬浮按钮的自由移动

1、自定义一个类FloatView继承自ImageView

public class FloatView extends ImageView{     private float mTouchX;     private float mTouchY;     private float x;     private float y;     private float mStartX;     private float mStartY;     private OnClickListener mClickListener;     private WindowManager windowManager = (WindowManager) getContext()             .getApplicationContext().getSystemService(Context.WINDOW_SERVICE);     // 此windowManagerParams变量为获取的全局变量,用以保存悬浮窗口的属性     private WindowManager.LayoutParams windowManagerParams = ((FloatApplication) getContext()             .getApplicationContext()).getWindowParams();     public FloatView(Context context) {         super(context);     }     @Override     public boolean onTouchEvent(MotionEvent event) {         //获取到状态栏的高度         Rect frame = new Rect();         getWindowVisibleDisplayFrame(frame);         int statusBarHeight = frame.top;         // 获取相对屏幕的坐标,悬浮窗口所在的位置        x = event.getRawX();         y = event.getRawY() - statusBarHeight; // statusBarHeight是系统状态栏的高度         switch (event.getAction()) {         case MotionEvent.ACTION_DOWN: // 捕获手指触摸按下动作             // 获取相对View的坐标,即以此View左上角为原点             mTouchX = event.getX();             mTouchY = event.getY();             mStartX = x;             mStartY = y;             break;         case MotionEvent.ACTION_MOVE: // 捕获手指触摸移动动作             updateViewPosition();             break;         case MotionEvent.ACTION_UP: // 捕获手指触摸离开动作             updateViewPosition();             mTouchX = mTouchY = 0;             if ((x - mStartX) < 5 && (y - mStartY) < 5) {                 if(mClickListener!=null) {                     mClickListener.onClick(this);                 }             }             break;         }         return true;    }     @Override     public void setOnClickListener(OnClickListener l) {         this.mClickListener = l;     }     private void updateViewPosition() {         // 更新浮动窗口位置参数         windowManagerParams.x = (int) (x - mTouchX);         windowManagerParams.y = (int) (y - mTouchY);         windowManager.updateViewLayout(this, windowManagerParams); // 刷新显示     } } 

2、定义一个FloatApplication类继承Application,为了防止悬浮按钮超出相应的范围

public class FloatApplication extends Application {     private WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();     public WindowManager.LayoutParams getWindowParams() {         return windowParams;     } } 

3、在相应的Activity中创建悬浮按钮

protected static void createFloatView(int paddingBottom) {          floatView = new FloatView(mContext);        floatView.setOnTouchListener(new OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent ev) {                int action=ev.getAction();                switch (action) {                case MotionEvent.ACTION_DOWN:                    v.setBackgroundResource(R.drawable.scan_ss);                    break;                case MotionEvent.ACTION_UP:                    v.setBackgroundResource(R.drawable.scan_sss);                    break;                default:                    break;                }                return false;            }        });        floatView.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View arg0) {                ATService.handler.obtainMessage(11).sendToTarget();            }        });         floatView.setImageResource(R.drawable.scan_sss); // 这里简单的用自带的icon来做演示         // 获取WindowManager         windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);         int screenWidth = windowManager.getDefaultDisplay().getWidth();          int screenHeight = windowManager.getDefaultDisplay().getHeight();          // 设置LayoutParams(全局变量)相关参数         windowManagerParams = ((FloatApplication) mContext.getApplicationContext()).getWindowParams();         windowManagerParams.type = LayoutParams.TYPE_PHONE; // 设置window type,主要是让悬浮按钮以什么类型显示         windowManagerParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明         // 设置Window flag         windowManagerParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL                 | LayoutParams.FLAG_NOT_FOCUSABLE;         /*          * flag的值可以为:          * LayoutParams.FLAG_NOT_TOUCH_MODAL 不影响后面的事件          * LayoutParams.FLAG_NOT_FOCUSABLE 不可聚焦          * LayoutParams.FLAG_NOT_TOUCHABLE 不可触摸          */         // 调整悬浮窗口至左上角,便于调整坐标         windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;         // 以屏幕左上角为原点,设置xy初始值 ,即控制悬浮按钮的初始位置        windowManagerParams.x = screenWidth;         windowManagerParams.y = screenHeight/2;         // 设置悬浮窗口长宽数据         windowManagerParams.width = LayoutParams.WRAP_CONTENT;         windowManagerParams.height = LayoutParams.WRAP_CONTENT;         // 显示myFloatView图像         windowManager.addView(floatView, windowManagerParams);        isFolat=true;    }  

注意 最后比忘记了在AndroidManifest.xml添加相应的权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />//修改application的android:name属性 就是把之前定义的FloatApplication,前面则是FloatApplication所在的包名<application        android:icon="@drawable/icon"        android:name="com.scpark.floatwindow.FloatApplication"        android:label="@string/application_label" >

4、自由移动悬浮按钮的打开和关闭的代码

createFloatView(100);//创建windowManager.removeView(floatView);//关闭悬浮按钮

希望对各位有所帮助,若有不对的地方,欢迎指证,谢谢。

更多相关文章

  1. Android的supportV7中默认按钮的颜色设置
  2. 输入法与窗口交互
  3. android studio 添加按钮点击事件的三种方法
  4. android 按钮 背景 文字 自定义
  5. appwidget中使按钮不能用 以及 appwidget初学指导
  6. Android控件ToggleButton多状态按钮使用详解
  7. Android图形显示之本地窗口

随机推荐

  1. Nginx服务器开箱体验
  2. 深入理解Java反射
  3. 通过动图学习 CSS Flex [每日前端夜话0x7
  4. SpringBoot应用部署于外置Tomcat容器
  5. 正确获取Android(安卓)IP、MAC姿势
  6. Redis 发布订阅,小功能大用处,真没那么废材
  7. 在 React 16 中从 setState 返回 null 的
  8. Groovy开箱初体验
  9. 服务应用突然宕机了?别怕,Dubbo 会帮你自动
  10. DoDAF2.0方法论探究