View的滑动方式有很多,在学习View的滑动之前,我们先了解下View是怎么定位的。
1.View自身坐标
getTop():获取自身顶部到父布局顶部的距离
getLeft():获取View自身左边到父布局左边的距离
getRight():获取View自身到父布局左边的距离
getBottom():获取View自身到父布局顶部的距离
2.确定点击位置坐标
当我们点击屏幕时,会触发点击事件。MotionEvent提供了几种方法获取点击坐标
view的滑动是当点击事件传递到View时,记下触摸点,当手指移动时,记录移动后的坐标并计算出偏移量,通过偏移量来改变View的坐标。
1.layout()
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;
layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
break;
}
}
2.offsetLeftAndRight()与offsetTopAndBottom()
将ACTION_MOVE中的layout方法替换就行
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
3.LayoutParams
通过改变LayoutParams来改变View 的布局参数,便改变了View的位置,同样替换ACTION_MOVE中的代码
int offsetX = x - lastX;
int offsetY = y - lastY;
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();
params.leftMargin = getLeft() + offsetX;
params.topMargin = getTop() + offsetY;
break;
4.scrollTo和scrollBy
scrollTo表示移动到具体的坐标点位置,scrollBy表示在原来View的基础上移动偏移量。需要注意的是,移动的偏移量要取反。因为这两个方法移动的是其内部的内容。
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
((View)getParent()).scrollBy(-offsetX,-offsetY);
break;
5.Scroller
可以通过Scroller来实现View移动的连续性。Scroller需要与View的computeScroll()方法配合。
scroller = new Scroller(context);
重写computeScroll方法,系统在调用draw()方法时,会调用此方法。在该方法中,调用父类的scrollTo方法,通过Scroller获取当前滚动值,滑动一小段距离后,调用invalidate()方法进行重绘。
@Override
public void computeScroll() {
super.computeScroll();
if (scroller.computeScrollOffset()) {
offsetLeftAndRight(scroller.getCurrX()-getLeft());
offsetTopAndBottom(scroller.getCurrY()-getTop());
invalidate();
}
}
最后调用Scroller中的startScroll方法。
scroller.startScroll(getLeft(),getTop(),-getLeft()+initX,-getTop()+initY,2000);