记得之前项目里面,写过这种需求,不过跟项目耦合的紧,又重网上找了几篇文章看了下,顺便也抄了下其他作者写的代码,如果需求场景比较简单,只是为了在当前手机屏幕里面拖动view,那么可以直接用本篇文章的代码,这里呢,有两个类,一个是自定义的ImageView,用于ImageView的任意拖拽效果,还有一个是fabButton的,可以任意拖拽fabButton。
代码比较简单,下次有类似简单需求,就可以直接抄代码了,不然还得找半天。我们先看ImageView的.
@SuppressLint("AppCompatCustomView") public class DragImageView extends ImageView { private int width; private int height; private int screenWidth; private int screenHeight; private Context context; //是否拖动 private boolean isDrag = false; private float downX; private float downY; public DragImageView(Context context) { super(context); this.context = context; } public DragImageView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public boolean isDrag() { return isDrag; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getMeasuredWidth(); height = getMeasuredHeight(); screenWidth = SystemUtils.getWindowWidth(); screenHeight = SystemUtils.getWindowHeight() - SystemUtils.getStatusBarHeight(); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); if (this.isEnabled()) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isDrag = false; downX = event.getX(); downY = event.getY(); break; case MotionEvent.ACTION_MOVE: final float xDistance = event.getX() - downX; final float yDistance = event.getY() - downY; int l, r, t, b; //当水平或者垂直滑动距离大于10,才算拖动事件 if (Math.abs(xDistance) > 10 || Math.abs(yDistance) > 10) { isDrag = true; l = (int) (getLeft() + xDistance); r = l + width; t = (int) (getTop() + yDistance); b = t + height; //不划出边界判断,此处应按照项目实际情况,因为本项目需求移动的位置是手机全屏, // 所以才能这么写,如果是固定区域,要得到父控件的宽高位置后再做处理 if (l < 0) { l = 0; r = l + width; } else if (r > screenWidth) { r = screenWidth; l = r - width; } if (t < 0) { t = 0; b = t + height; } else if (b > screenHeight) { b = screenHeight; t = b - height; } this.layout(l, t, r, b); } break; case MotionEvent.ACTION_UP: setPressed(false); break; case MotionEvent.ACTION_CANCEL: setPressed(false); break; } return true; } return false; } }
接着在看看FabButton的吧,其实代码是差不多的
public class DragFloatingActionButton extends FloatingActionButton { private int width; private int height; private int screenWidth; private int screenHeight; private Context context; //是否拖动 private boolean isDrag = false; private float downX; private float downY; public DragFloatingActionButton(Context context) { super(context); this.context = context; } public DragFloatingActionButton(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public boolean isDrag() { return isDrag; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getMeasuredWidth(); height = getMeasuredHeight(); screenWidth = SystemUtils.getWindowWidth(); screenHeight = SystemUtils.getWindowHeight() - SystemUtils.getStatusBarHeight(); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); if (this.isEnabled()) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isDrag = false; downX = event.getX(); downY = event.getY(); break; case MotionEvent.ACTION_MOVE: final float xDistance = event.getX() - downX; final float yDistance = event.getY() - downY; int l, r, t, b; //当水平或者垂直滑动距离大于10,才算拖动事件 if (Math.abs(xDistance) > 10 || Math.abs(yDistance) > 10) { isDrag = true; l = (int) (getLeft() + xDistance); r = l + width; t = (int) (getTop() + yDistance); b = t + height; //不划出边界判断,此处应按照项目实际情况,因为本项目需求移动的位置是手机全屏, // 所以才能这么写,如果是固定区域,要得到父控件的宽高位置后再做处理 if (l < 0) { l = 0; r = l + width; } else if (r > screenWidth) { r = screenWidth; l = r - width; } if (t < 0) { t = 0; b = t + height; } else if (b > screenHeight) { b = screenHeight; t = b - height; } this.layout(l, t, r, b); } break; case MotionEvent.ACTION_UP: setPressed(false); break; case MotionEvent.ACTION_CANCEL: setPressed(false); break; } return true; } return false; } }
核心逻辑是在onTouchEvent里面的判断。有需要研究的可以自己分析。
如果view需要处理点击事件呢。
那么代码上的用法需要注意下,参考如下的姿势:
dragView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("TEST", "onClick() dragView 111"); if (dragView.isDrag()) { return; } Log.e("TEST", "onClick() dragView 222"); Toast.makeText(MainActivity.this, "哈哈", Toast.LENGTH_SHORT).show(); } });
写这篇是为了记录,像这种不经常写的代码(需求场景简单的),放个地方托管,方便下次复制粘贴。