View位置的变化和触控操作都涉及到MotionEvent
类,MotionEvent
中封装了一些与触摸相关的东西,比如触摸事件Action
,触摸坐标等。移动View
无疑就是改变其位置,通常有以下几种方式。
在View
类中,我们知道有一个layout
方法是给View
定位的 ,结合onTouchEvent
方法 ,我们可以很好的实现一个View
的移动.
int lastX, lastY; @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; layout(getLeft()+offsetX, getTop()+offsetY, getRight()+offsetX, getBottom()+offsetY); lastX = rawX; lastY = rawY; break; } return true; }12345678910111213141516171819202122232425262728293031323334
这里面使用了绝对坐标,使用绝对坐标的时候,需要在每次ACTION_MOVE
后重新设置初始坐标.
使用offsetLeftAndRight();offsetTopAndBottom();
方法,通过设置偏移量来滑动View
int lastX, lastY; @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; //layout(getLeft()+offsetX, // getTop()+offsetY, // getRight()+offsetX, // getBottom()+offsetY); offsetLeftAndRight(offsetX); offsetTopAndBottom(offsetY); lastX = rawX; lastY = rawY; break; } return true; }12345678910111213141516171819202122232425262728293031323334353637
LayoutParams
,使用LayoutParams
滑动View
,通过改变布局参数来达到滑动View
的目的.
int lastX, lastY; @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; // layout(getLeft()+offsetX, // getTop()+offsetY, // getRight()+offsetX, // getBottom()+offsetY);// offsetLeftAndRight(offsetX);// offsetTopAndBottom(offsetY); ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams(); layoutParams.leftMargin = getLeft() + offsetX ; layoutParams.topMargin = getTop() +offsetY; setLayoutParams(layoutParams); lastX = rawX; lastY = rawY; break; } return true; }123456789101112131415161718192021222324252627282930313233343536373839404142
使用ScrollTo() 和ScrollBy()
方法来改变View
的位置.
int lastX, lastY; @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; // layout(getLeft()+offsetX, // getTop()+offsetY, // getRight()+offsetX, // getBottom()+offsetY);// offsetLeftAndRight(offsetX);// offsetTopAndBottom(offsetY);// ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();// layoutParams.leftMargin = getLeft() + offsetX ;// layoutParams.topMargin = getTop() +offsetY;// setLayoutParams(layoutParams); ((View) getParent()).scrollBy( -offsetX, -offsetY); lastX = rawX; lastY = rawY; break; } return true; }123456789101112131415161718192021222324252627282930313233343536373839404142434445
这里需要注意的是
1.首先我们的ScrollTo() and ScrollBy()
方法移动的是View的Content
2.我们移动的是画布,因此需要设置相反的值,才能让View
跟随手指移动.
使用Scroller
类来移动View
,与ScrollBy()
方法关系紧密,ScrollBy()
移动是瞬时完成,Scroller
类在ACTION_MOVE
中对偏移量进行划分,达到平滑效果.我们需要三个步骤
mScroller = new Scroller(context);1
@Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { ((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }12345678
case MotionEvent.ACTION_UP: ViewGroup viewGroup = (ViewGroup) getParent(); mScroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY()); invalidate(); break;1234567
通过 属性动画对View
位置对改变
int w = text.getWidth(); int screenW = UiUtil.getScreenWidth(); int transX = screenW - w; ObjectAnimator transAnim = ObjectAnimator.ofFloat(text, "translationX", 0, transX);1234
使用v4包中的ViewDragHelper
能很好的实现View
的滑动和事件分发,典型谷歌官方的 Drawerlayout
实例:ViewDragHelper实现QQ侧滑效果DragLayout[github]