62.悬浮所有页面之上、可拖拽的交互按钮FloatDragView

转载请注明出处 http://blog.csdn.net/qq_31715429/article/details/77895842
本文出自:猴菇先生的博客

一个项目在开发的过程中,网络请求一般使用的是测试地址,开发完成可能还有仿真环境地址,然后是正式地址。那么在开发和测试的过程中,就需要动态切换请求地址。这就需要一个类似Spinner的下拉框来完成这个功能,一开始我是写在Main页面,就一个简单的Spinner,但是限制是如果跳转到更深层次的页面,就切换不了链接地址了。这就需要使用WindowManager创建一个view,使之悬浮于所有activity之上,随时随地切换地址。效果如下:

这里写图片描述

有没有萌化你的少女心啊,哈哈。。
代码已上传至 https://github.com/MonkeyMushroom/FloatDragView
图片来自iconfont,仅供学习交流使用,不得用于商业用途。

1.创建一个FloatDragViewManager来管理WindowManager添加删除view

public class FloatDragViewManager implements FloatDragView.OnClickListener, FloatDragView.OnScrollListener {

	private WindowManager mWindowManager;
    private WindowManager.LayoutParams mFdvParams;
	private Context mContext;

	public void showFloatDragView() {
        mContext = BaseApplication.getInstance();
        mWindowManager = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
        mFloatDragView = new FloatDragView(mContext);//是一个自定义的可拖拽的view,下面会写
        mFloatDragView.setOnClickListener(this);
        mFloatDragView.setOnScrollListener(this);
        mFloatDragView.setText(mUrlArr[0]);
        mFdvParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mFdvParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            mFdvParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        mFdvParams.format = PixelFormat.TRANSPARENT;//背景透明
        mFdvParams.gravity = Gravity.LEFT | Gravity.TOP;//位置
        mFdvParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        mFdvParams.width = WindowManager.LayoutParams.WRAP_CONTENT;//宽高
        mFdvParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowManager.addView(mFloatDragView, mFdvParams);
    }
}

别忘了要有权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

并在设置中也要找到该应用,打开悬浮窗权限。

我在Main页中显示悬浮窗:

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mManager = new FloatDragViewManager();
        mManager.showFloatDragView();
    }

这时就应该可以看见了。

2.点击悬浮窗显示一个RecyclerView,提供点击事件改变链接地址:

	private RecyclerView mSpinnerRv;
	private WindowManager.LayoutParams mRvParams;
	
    private String[] mUrlArr = new String[]{"测试", "正式", "仿真"};
    private boolean mIsSpinnerShow;//列表是否显示的状态
    
	@Override
    public void onClick() {
        if (mSpinnerRv == null) {
            mSpinnerRv = new RecyclerView(mContext);
            mSpinnerRv.setBackgroundResource(R.drawable.corner_cyan_bg);
            mSpinnerRv.setLayoutManager(new LinearLayoutManager(mContext));
            mSpinnerRv.addOnItemTouchListener(new OnItemClickListener() {
                @Override
                public void onSimpleItemClick(BaseQuickAdapter adapter, View view, int position) {
                    mFloatDragView.setText(mUrlArr[position]);
                    Constant.BASE_URL = Constant.URL_ARR[position];
                    Toast.makeText(mContext, Constant.BASE_URL, Toast.LENGTH_SHORT).show();
                    mWindowManager.removeView(mSpinnerRv);//移除列表
                    mIsSpinnerShow = false;
                }
            });
            mSpinnerRv.setAdapter(new DataAdapter());
        }
        if (mIsSpinnerShow) {//移除列表
            mWindowManager.removeView(mSpinnerRv);
        } else {//添加列表
            mRvParams = new WindowManager.LayoutParams();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                mRvParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            } else {
                mRvParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            }
            mRvParams.gravity = Gravity.LEFT | Gravity.TOP;
            mRvParams.format = PixelFormat.TRANSPARENT;
            mRvParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
            mRvParams.x = mFdvParams.x;//列表位置在FloatDragView之下
            mRvParams.y = mFdvParams.y + mFloatDragView.getHeight();
            mRvParams.width = mFloatDragView.getWidth();
            mRvParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
            mWindowManager.addView(mSpinnerRv, mRvParams);
        }
        mIsSpinnerShow = !mIsSpinnerShow;
    }

这时就已经可以实现点击切换地址了,但是不能拖动的话会挡住其他view

3.FloatDragView实现拖拽:

	private float mTouchX;
    private float mTouchY;
    private float mStartX;
    private float mStartY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getRawX();
        float y = event.getRawY() - getStatusBarHeight(getContext());
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mTouchX = event.getX();
                mTouchY = event.getY();
                mStartX = x;
                mStartY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mOnScrollListener != null) {
                    mOnScrollListener.onScroll((int) (x - mTouchX), (int) (y - mTouchY));
                }
                break;
            case MotionEvent.ACTION_UP:
                mTouchX = mTouchY = 0;
                if (Math.abs(x - mStartX) < 5 && Math.abs(y - mStartY) < 5) {// 用于区别是滑动了还是点击了
                    if (mOnClickListener != null) {
                        mOnClickListener.onClick();
                    }
                }
                break;
        }
        return true;
    }
    
    /**
     * 滑动监听,供外部调用 
     */
	public void setOnScrollListener(OnScrollListener onScrollListener) {
        mOnScrollListener = onScrollListener;
    }

    public interface OnScrollListener {
        void onScroll(int x, int y);
    }

在manager中:

	/**
     * 滑动监听,动态改变按钮和列表的位置
     */
    @Override
    public void onScroll(int x, int y) {
        mFdvParams.x = x;
        mFdvParams.y = y;
        mWindowManager.updateViewLayout(mFloatDragView, mFdvParams);//更新位置
        if (mIsSpinnerShow) {//如果列表显示的话
            mRvParams.x = mFdvParams.x;
            mRvParams.y = mFdvParams.y + mFloatDragView.getHeight();
            mWindowManager.updateViewLayout(mSpinnerRv, mRvParams);
        }
    }

4.最后在FloatDragViewManager中添加消除view的方法:

    public void removeFloatDragView() {
        mWindowManager.removeView(mFloatDragView);
        if (mSpinnerRv != null && mIsSpinnerShow) {
            mWindowManager.removeView(mSpinnerRv);
        }
    }

在Main中调用:

	@Override
    protected void onDestroy() {
        super.onDestroy();
        mManager.removeFloatDragView();
    }

代码已上传至 https://github.com/MonkeyMushroom/FloatDragView

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值