Android WindowManager 全局悬浮窗 + AccessibilityService+ RecyclerView 拖动和点击

2020/10/10 15:06
阅读数 3.8K

在做辅助器的时候 要搞一个全局弹窗,用的 RecyclerView 加载了一些按钮,其中遇到一个小问题 ,就是拖动 RecyclerView 时发现手指坐标不对,研究了一下 发现是初始化的问题。

具体看代码中的注释即可。

在这里插入图片描述


重点在于

 myFloatViewParama.setX( (int) event.getRawX() );
 myFloatViewParama.setY((int) event.getRawY());
/**viewGroup 拦截手势 实现 可以拖动viewgroup 时不影响 其中的view的点击事件。
 */
public class MyRecyclerView extends  RecyclerView{
    private int minTouchSlop=0;
    private float mDownX;
    private float mDownY;
    
    public MyRecyclerView(@NonNull Context context) {
        this(context ,null);
    }

    public MyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context ,attrs ,0);
    }

    public MyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(context);
    }

    private void initView(Context context){
        minTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    /**
     * todo onInterceptTouchEvent 用来决定是否拦截事件。
     * 判断出为拖动手势就把事件拦截下来,实现viewGroup的拖动效果。
     * 如果是点击效果 就不拦截事件,让子 view 响应点击事件。
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean interceptd  =false ;

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                interceptd = false;
                mDownX = event.getX();
                mDownY = event.getY();
                // todo 重要点,要在此处初始化位置参数,否则拖动时效果有偏差。
                // 因为 onTouchEvent 的 MotionEvent.ACTION_DOWN 不一定会被触发。
                myFloatViewParama.setX( (int) event.getRawX() );
                myFloatViewParama.setY((int) event.getRawY());
                break;

            case MotionEvent.ACTION_MOVE:
                float dx = event.getX() - mDownX;
                float dy = event.getY() - mDownY;
                // 根据滑动的距离来判断是否是拖动操作
                interceptd =   Math.abs(dx) > minTouchSlop || Math.abs(dy) > minTouchSlop  ;
                break;

            case MotionEvent.ACTION_UP:
                interceptd = false;
                break;
        }
        return interceptd;
    }

    private MyFloatViewParama myFloatViewParama ;
    private WindowManager windowManager ;
    public void updateConfig(MyFloatViewParama myFloatViewParama, WindowManager windowManager){
        this.myFloatViewParama =myFloatViewParama ;
        this.windowManager=windowManager;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if(myFloatViewParama==null){
            return false ;
        }

        if(windowManager ==null){
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //todo 因为 ViewGroup 中有 子View 被挡触摸时, ViewGroup ACTION_DOWN 没法被
                // 触发,所以为了确保触发,要在 onInterceptTouchEvent ACTION_DOWN 中进行初始化。
                myFloatViewParama.setX( (int) event.getRawX() );
                myFloatViewParama.setY((int) event.getRawY());
                break;
            case MotionEvent.ACTION_MOVE:
                int nowX = (int) event.getRawX();
                int nowY = (int) event.getRawY();
                int movedX = nowX -  myFloatViewParama.getX();
                int movedY = nowY -  myFloatViewParama.getY();
                myFloatViewParama.setX( nowX );
                myFloatViewParama.setY( nowY );
                myFloatViewParama.getLayoutParams().x = myFloatViewParama.getLayoutParams().x + movedX;
                myFloatViewParama.getLayoutParams().y = myFloatViewParama.getLayoutParams().y + movedY;
                windowManager.updateViewLayout(this, myFloatViewParama.getLayoutParams());
                break;
            case MotionEvent.ACTION_UP:
                performClick(); 
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }
}

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部