android提供了GestureDetector
这个类用于常用手势识别, 如单击、双击、滑动等; 对于拖拽手势的分析识别并不理性,
因此support-v4包提供了一个工具类ViewDragHelper, 使用此工具类可以轻松实现可拖拽View(准确的说应该是支持拖拽的View容器),
闲话少说, 请看代码:
DragContainerLayout.java
/**
* ViewDragHelper的用法
* 1. ViewDragHelper.create()创建实例
* 2. 初始化callback
* 3. 将当前ViewGroup的onInterceptTouchEvent和onTouchEvent事件委托给ViewDragHelper处理
* 4. 处理拖拽view的边界(在callback中的clampViewPositionHorizontal和clampViewPositionVertical方法中处理)
*/
public class DragContainerLayout extends LinearLayout{
private ViewDragHelper mViewDragHelper;
public DragContainerLayout(Context context) {
super(context);
initViewDragHelper();
GestureDetector
}
public DragContainerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initViewDragHelper();
}
public DragContainerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initViewDragHelper();
}
public DragContainerLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initViewDragHelper();
}
private void initViewDragHelper() {
//ViewDragHelper.Callback是一个抽象类, 里面有更多的处理, 将需要处理的方法重写就可以了
mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
Log.e("abc", "pointerId=" + pointerId);
//第3个view不能截取事件 (也就是不能拖拽)
if(getChildCount() >= 3) {
if(child == getChildAt(2)) {
return false;
}
}
return true; //true表示child可以拖拽, false标示child不能拖拽
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
final int leftBound = getPaddingLeft();
final int rightBound = getWidth() - child.getWidth() - getPaddingRight();
// int newLeft = left;
// if(left < leftBound) newLeft = leftBound;
// if(left > rightBound) newLeft = rightBound;
//词句等价于上面的三句
int newLefth = Math.min(Math.max(left, leftBound), rightBound);
return newLefth;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
final int topBound = getPaddingTop();
final int bottomBound = getHeight() - child.getHeight() - getPaddingBottom();
int newTop = Math.min(bottomBound, Math.max(topBound, top));
return newTop;
}
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
if(action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mViewDragHelper.cancel();
return false;
}
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.stone.android_demo2.DragContainerLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:paddingTop="60dp"
android:paddingLeft="0dp"
android:paddingBottom="0dp"
android:paddingRight="30dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"
android:padding="10dp"
android:background="#4400ccaa"
android:layout_marginTop="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="哈哈哈哈哈"
android:padding="10dp"
android:background="#4400ccaa"
android:layout_marginTop="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="wakaka"
android:padding="10dp"
android:background="#4400ccaa"
android:layout_marginTop="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hi, hi, you you !"
android:padding="10dp"
android:background="#4400ccaa"
android:layout_marginTop="10dp"/>
</com.stone.android_demo2.DragContainerLayout>
</LinearLayout>
创建一个Activity, 使用上述布局, 运行, 试试拖拽TextView