記得之前項目里面,寫過這種需求,不過跟項目耦合的緊,又重網上找了幾篇文章看了下,順便也抄了下其他作者寫的代碼,如果需求場景比較簡單,只是為了在當前手機屏幕里面拖動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(); } });
寫這篇是為了記錄,像這種不經常寫的代碼(需求場景簡單的),放個地方托管,方便下次復制粘貼。