+++++++++++++++++++++++++++++++方法1++++++++++++++++++++++++++++++++++++
activity_main.xml布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.example.draghelper.CustomView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FFFF0000" />
</com.example.draghelper.CustomView>
</RelativeLayout>
CustomView 代码注释很详细了
package com.example.draghelper;
import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;
public class CustomView extends LinearLayout {
private ViewDragHelper mDragHelper;
private Context context;
/****************************************************
* 三个构造器
*/
public CustomView(Context context) {
super(context);
this.context = context;
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init();
}
/**
* @params ViewGroup forParent 一个ViewGroup, 也就是ViewDragHelper将要用来拖拽谁下面的子view
* @params float sensitivity 灵敏度,一般1.0f即可
* @params Callback cb 一个回调,用来处理拖动到位置
*/
private void init() {
mDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragCallback());
}
/**
*表示尝试捕获子view,这里一定要返回true, 返回true表示允许。
*child 尝试捕获的view
*@param int pointerId 指示器id? 这里可以决定哪个子view可以拖动
*/
private class ViewDragCallback extends ViewDragHelper.Callback {
@Override
public boolean tryCaptureView(View view, int pointerId) {
return true;
}
/********************************************************************
* 这两个方法分别用来处理x方向和y方向的拖动的,返回值该child现在的位置。
* @param View child 被拖动到view
* @param int left 移动到达的x轴的距离
* @param int dx 建议的移动的x距离
* clampViewPositionHorizontal的第二个参数是指当前拖动子view应该到达的x坐标。
* 所以按照常理这个方法原封返回第二个参数就可以了,但为了让被拖动的view遇到边界之后就不在拖动,对返回的值做了更多的考虑
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
Toast.makeText(context, "left = " + left + ", dx = " + dx, 0).show();
// 两个if主要是为了让viewViewGroup里
if (getPaddingLeft() > left) {
return getPaddingLeft();
}
if (getWidth() - child.getWidth() < left) {
return getWidth() - child.getWidth();
}
return left;
}
/**
* 处理竖直方向上的拖动
*
* @param View
* child 被拖动到view
* @param int top 移动到达的y轴的距离
* @param int dy 建议的移动的y距离
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
// 两个if主要是为了让viewViewGroup里
if (getPaddingTop() > top) {
return getPaddingTop();
}
if (getHeight() - child.getHeight() < top) {
return getHeight() - child.getHeight();
}
return top;
}
/**
* 当拖拽到状态改变时回调
*
* @params 新的状态
*/
@Override
public void onViewDragStateChanged(int state) {
switch (state) {
case ViewDragHelper.STATE_DRAGGING: // 正在被拖动
break;
case ViewDragHelper.STATE_IDLE: // view没有被拖拽
break;
case ViewDragHelper.STATE_SETTLING: // fling完毕后被放置到一个位置
break;
}
super.onViewDragStateChanged(state);
}
}
/****************************************************************
* 一但返回True(代表事件在当前的viewGroup中会被处理)
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
/**
* 比如当你的手指在屏幕上拖动一个listView或者一个ScrollView而不是去按上面的按钮时会触发这个事件
*/
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
mDragHelper.cancel(); // 类似onTouch的ACTION_UP事件,清除
break;
}
/**
* 是否应该打断该MotionEvent的传递
*/
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
/**
* 处理拦截到的事件 这个方法会在返回前分发事件
*/
mDragHelper.processTouchEvent(event);
/**
* return true 表示消费了事件。
*/
return true;
}
}
+++++++++++++++++++++++++++++++方法2++++++++++++++++++++++++++++++++++++
DragLayout
package com.example.demo;
import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
public class DragLayout extends RelativeLayout {
private final ViewDragHelper mDragHelper;
final ViewDragHelper.Callback mDragCallBack = new ViewDragHelper.Callback() {
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
};
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return top;
};
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
invalidate();
}
/**
* 通过DragHelperCallback的tryCaptureView方法的返回值可以决定一个parentview中哪个子view可以拖动
*/
@Override
public boolean tryCaptureView(View arg0, int arg1) {
return true;
}
};
public DragLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mDragHelper = ViewDragHelper.create(this, 1.0f, mDragCallBack);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
}
++++++++++++++++++++方法3++++++++++++++++++++++++
http://blog.csdn.net/u013210620/article/details/46378231