方法一
通过layout()方法实现,代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 记录触摸点坐标
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
// 计算偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
// 在当前left、top、right、bottom的基础上加上偏移量
layout(getLeft() + offsetX,
getTop() + offsetY,
getRight() + offsetX,
getBottom() + offsetY);
// offsetLeftAndRight(offsetX);
// offsetTopAndBottom(offsetY);
break;
}
return true;
如果使用绝对坐标getRawX,getRawY,需要在每次执行完ACTION_MOVE的逻辑后,重新设置初始坐标,代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) (event.getRawX());
int rawY = (int) (event.getRawY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
// 计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
// 在当前left、top、right、bottom的基础上加上偏移量
layout(getLeft() + offsetX,
getTop() + offsetY,
getRight() + offsetX,
getBottom() + offsetY);
// 重新设置初始坐标
lastX = rawX;
lastY = rawY;
break;
}
return true;
}
至于为什么要在最后使用初始化,
http://blog.csdn.net/yiwei12/article/details/71122892#comments
- 方法二
使用LayoutParams设置,控件外是LinearLayout就使用LinearLayout.LayoutParams,是RelativeLayout就使用RelativeLayout.LayoutParams。
但是使用ViewGroup.MarginLayoutParams更加方便,不需要考虑父布局的类型。
代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 记录触摸点坐标
lastX = (int) event.getX();
lastY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
// 计算偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
// LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft() + offsetX;
layoutParams.topMargin = getTop() + offsetY;
setLayoutParams(layoutParams);
break;
}
return true;
}
- 方法三
使用ScrollBy或者ScrollTo()方法(ScrollBy和ScrollTo的区别?By是移动多少,To是移动到哪里)。
需要注意这两个方法移动的是屏幕,而不是控件,所以需要取offsetX,offsetY的相反数。
并且这两个方法是移动控件的内容(即如果View是TextView,那么移动的就是它的文本)所以这里需要在前面使用((View) getParent())。
代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getX();
lastY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
((View) getParent()).scrollBy(-offsetX, -offsetY);
break;
}
return true;
}
- 方法四
使用Scroller类,实现放手View自动移动到原位
代码如下:
private void ininView(Context context) {
setBackgroundColor(Color.BLUE);
// 初始化Scroller
mScroller = new Scroller(context);
}
@Override
public void computeScroll() {
super.computeScroll();
// 判断Scroller是否执行完毕
if (mScroller.computeScrollOffset()) {
((View) getParent()).scrollTo(
mScroller.getCurrX(),
mScroller.getCurrY());
// 通过重绘来不断调用computeScroll
invalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getX();
lastY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
((View) getParent()).scrollBy(-offsetX, -offsetY);
break;
case MotionEvent.ACTION_UP:
// 手指离开时,执行滑动过程
View viewGroup = ((View) getParent());
mScroller.startScroll(
viewGroup.getScrollX(),
viewGroup.getScrollY(),
-viewGroup.getScrollX(),
-viewGroup.getScrollY());
invalidate();
break;
}
return true;
}
/参考自 Android群英传