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