在做辅助器的时候 要搞一个全局弹窗,用的 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();
}
}