頁面中可拖拽控制元件的簡單實現方案
阿新 • • 發佈:2019-01-28
頁面中可拖拽控制元件的簡單實現,可直接一句話實現.
核心程式碼邏輯類如下:
import android.animation.ObjectAnimator;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.DecelerateInterpolator;
/**
* 控制元件拖動邏輯處理
* Created by WQ on 2017/10/23.
*/
public class ViewDragMode implements View.OnTouchListener{
private View targetView;
public ViewDragMode(final View targetView) {
this.targetView=targetView;
this.targetView.setOnTouchListener(this);
}
private int parentHeight;
private int parentWidth;
private int lastX;
private int lastY;
private boolean isDrag;
@Override
public boolean onTouch(View v, MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
targetView.setPressed(true);
isDrag = false;
ViewParent viewParent = targetView.getParent();
viewParent.requestDisallowInterceptTouchEvent(true);
lastX = rawX;
lastY = rawY;
ViewGroup parent;
parent = (ViewGroup) viewParent;
parentHeight = parent.getHeight();
parentWidth = parent.getWidth();
break;
case MotionEvent.ACTION_MOVE:
if (parentHeight <= 0 || parentWidth == 0) {
isDrag = false;
break;
} else {
isDrag = true;
}
int dx = rawX - lastX;
int dy = rawY - lastY;
//這裡修復一些華為手機無法觸發點選事件
int distance = (int) Math.sqrt(dx * dx + dy * dy);
if (distance == 0) {
isDrag = false;
break;
}
float x = targetView.getX() + dx;
float y = targetView.getY() + dy;
//檢測是否到達邊緣 左上右下
x = x < 0 ? 0 : x > parentWidth - targetView.getWidth() ? parentWidth - targetView.getWidth() : x;
y = targetView.getY() < 0 ? 0 : targetView.getY() + targetView.getHeight() > parentHeight ? parentHeight - targetView.getHeight() : y;
targetView.setX(x);
targetView.setY(y);
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (!isNotDrag()) {
//恢復按壓效果
targetView.setPressed(false);
if (rawX >= parentWidth / 2) {
//靠右吸附
targetView.animate().setInterpolator(new DecelerateInterpolator())
.setDuration(500)
.xBy(parentWidth - targetView.getWidth() - targetView.getX())
.start();
} else {
//靠左吸附
ObjectAnimator oa = ObjectAnimator.ofFloat(targetView, "x", targetView.getX(), 0);
oa.setInterpolator(new DecelerateInterpolator());
oa.setDuration(500);
oa.start();
}
}
break;
}
//如果是拖拽則消s耗事件,否則正常傳遞即可。
return !isNotDrag() || targetView.onTouchEvent(event);
}
/**
* 是否拖拽中
* @return
*/
public boolean isDraging(){
return isDrag;
}
private boolean isNotDrag() {
if(targetView ==null)return true;
return !isDrag ;
}
}
使用方法:
ViewDragMode(targetView)
targetView 為懸浮可拖拽的目標控制元件.實現的效果是,該控制元件可在父容器範圍內進行拖拽,並自動左右吸邊.
該工具類提供isDraging()
方法判斷是否處於拖拽中,用於解決一些滑動衝突的問題.