— Android群英传读书笔记
概述
View位置的变化和触控操作都涉及到MotionEvent
类,MotionEvent
中封装了一些与触摸相关的东西,比如触摸事件Action
,触摸坐标等。移动View
无疑就是改变其位置,通常有以下几种方式。
layout
在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;
}
这里面使用了绝对坐标,使用绝对坐标的时候,需要在每次ACTION_MOVE
后重新设置初始坐标.
offsetLeftAndRight()
使用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;
}
过offset值改变View的getTop()、getBottom(),getRight(),getLeft()的值
LayoutParams
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;
}
ScrollTo() ScrollBy()
使用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;
}
这里需要注意的是
1.首先我们的ScrollTo() and ScrollBy()
方法移动的是View的Content
2.我们移动的是画布,因此需要设置相反的值,才能让View
跟随手指移动.
Scroller
使用Scroller
类来移动View
,与ScrollBy()
方法关系紧密,ScrollBy()
移动是瞬时完成,Scroller
类在ACTION_MOVE
中对偏移量进行划分,达到平滑效果.我们需要三个步骤.
mScroller = new Scroller(context);
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
}
}
case MotionEvent.ACTION_UP:
ViewGroup viewGroup = (ViewGroup) getParent(); mScroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY());
invalidate();
break;
computeScroll
判断是否滑动结束,进而进行滑动,之后通过invalidate()
刷新界面调用onDraw
方法
Property Animation
通过 属性动画对View
位置对改变
int w = text.getWidth();
int screenW = UiUtil.getScreenWidth();
int transX = screenW - w;
ObjectAnimator transAnim = ObjectAnimator.ofFloat(text, "translationX", 0, transX);
ViewDragHelper
使用v4包中的ViewDragHelper
能很好的实现View
的滑动和事件分发,典型谷歌官方的 Drawerlayout
ViewDragHelper
封装了滚动操作,其内部使用了Scroller
,关于ViewDragHelper
的介绍网上也很多,重要的就是其内部类ViewDragHelper.callback
,我们只需要按需复写即可.