简介
ViewDragHelper是什么?顾名思义,就是拖拽控件的一个帮助类。通过这个帮助类,我们可以轻松实现一些拖动效果。
基本使用
public class MyLinearLayout extends LinearLayout {
private ViewDragHelper dragHelper;
public MyLinearLayout(Context context) {
this(context, null);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
/**
* 初始化
*/
private void init() {
dragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
/**
* tryCaptureView:如果返回true表示捕获相关View
*
* 你可以根据第一个参数child决定捕获哪个View,这样 return child == yourView;
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
/**
* clampViewPositionVertical:计算child垂直方向的位置,top表示y轴坐标(相对于ViewGroup),默认返回0(如果不复写该方法)
* 这里,你可以控制垂直方向可移动的范围
* */
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return top;
}
/**
* clampViewPositionHorizontal:与clampViewPositionVertical类似,只不过是控制水平方向的位置
* */
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
});
}
/**
* 如果你希望拖拽的子View是不可点击的,可以不重写onInterceptTouchEvent方法
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return dragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
dragHelper.processTouchEvent(event);
return true;
}
}
<?xml version="1.0" encoding="utf-8"?>
<com.example.viewdraghelper.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TestActivity"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:background="@color/colorPrimaryDark"
android:textColor="@android:color/white"
android:text="我可以被拖拽"
android:id="@+id/dragView1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:layout_marginTop="10dp"
android:text="我也可以被拖拽"
android:background="@color/colorPrimaryDark"
android:textColor="@android:color/white"
android:id="@+id/dragView2"/>
</com.example.viewdraghelper.MyLinearLayout>
以上就是基本使用,效果请看gif
![](https://i-blog.csdnimg.cn/blog_migrate/ef854bf780e7ccd23d77d136654b2685.gif)
通过上面的gif我们可以看到,图片在拖拽的时候会超出边界,那么,现在就来处理一下拖动边界的问题。
public class MyLinearLayout extends LinearLayout {
private ViewDragHelper dragHelper;
public MyLinearLayout(Context context) {
this(context, null);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
/**
* 初始化
*/
private void init() {
dragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
/**
* tryCaptureView:如果返回true表示捕获相关View
*
* 你可以根据第一个参数child决定捕获哪个View,这样 return child == yourView;
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
/**
* clampViewPositionVertical:计算child垂直方向的位置,top表示y轴坐标(相对于ViewGroup),默认返回0(如果不复写该方法)
* 这里,你可以控制垂直方向可移动的范围
* */
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
// 上边距
if(top < 0){
top = 0;
}
// 下边距
if(top > getHeight() - child.getMeasuredHeight()){
top = getHeight() - child.getMeasuredHeight();
}
return top;
}
/**
* clampViewPositionHorizontal:与clampViewPositionVertical类似,只不过是控制水平方向的位置
* */
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
// 左边距
if(left < 0){
left = 0;
}
// 右边距
if(left > getWidth() - child.getMeasuredWidth()){
left = getWidth() - child.getMeasuredWidth();
}
return left;
}
/**
* 处理点击事件和滑动事件的冲突
*
* 设置
* */
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight() - child.getMeasuredHeight();
}
/**
* 处理点击事件和滑动事件的冲突
* */
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth() - child.getMeasuredWidth();
}
});
}
/**
* 如果你希望拖拽的子View是不可点击的,可以不重写onInterceptTouchEvent方法
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return dragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
dragHelper.processTouchEvent(event);
return true;
}
}
运行后的效果如图:
![边界控制](https://i-blog.csdnimg.cn/blog_migrate/38b58c612ff7252bf00c03d28150022e.gif)