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

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);//关闭悬浮按钮

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

你可能感兴趣的:(android点滴)