实现滑动的几种方法

来源:互联网 发布:mysql怎么备份数据库 编辑:程序博客网 时间:2024/05/22 04:08

本文主要讲述几种常用的滑动方法,顺便使用一下触控事件MotionEvent


MotionEvent的触控事件

通常我们会在onTouchEvent(MotionEvent event)方法中来获取触控的事件然后swith-case方法来进行筛选操作

代码基本固定如下

public boolean onTouchEvent(MotionEvent event) {    int x = (int) event.getX();    int y = (int) event.getY();    switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            break;        case MotionEvent.ACTION_MOVE:            break;        case MotionEvent.ACTION_UP:            break;        case MotionEvent.ACTION_CANCEL:            break;        case MotionEvent.ACTION_OUTSIDE:            break;        case MotionEvent.ACTION_POINTER_DOWN:            break;        case MotionEvent.ACTION_POINTER_UP:            break;    }    return true;}
滑动实现的基本思想大致都是一样的
1⃣️系统记下当前的触摸点坐标2⃣️系统记下手指移动后的坐标,从而获取前一次坐标点的偏移量3⃣️通过偏移量修改view的坐标,不断重复,从而实现滑动效果
以下所有的方法都是在重写的view里面执行的,所操作的移动的控件也是我们重写的view
public class DragView extends View {...}

第一种 使用layout方法,(不会改变父布局内其他空间的位置)这下面也有两张不同的小方法,主要是在对获取坐标问题不同上而出来的两种方法 具体的坐标系获取坐标的各种方法的区别会在下篇博客中罗列以下
①使用event.getX()和event.getY()记录坐标
@Overridepublic 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);            break;    }    return true;}
②使用event.getRawX()和event.getRawY()记录坐标(绝对坐标)    注意:使用绝对坐标时每次执行完ACTION_MOVE后一定要重新设置初始坐标,这样才能准确的获取偏移量
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;}
第二种使用系统封装好的方法 不会改变父布局内其他空间的位置
offsetLeftAndRight(int dx);offsetTopAndBottom(int dy);
这两个相当于系统提供的一个对左右、上下移动的方法封装。dx、dy是计算的偏移量
@Overridepublic 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;}
第三种使用LayoutParams方法   会改变父布局内其他空间的布局
具体是改变LayoutParams下leftMargin和rightMargin的属性(边距),然后使用setLayoutParams(...)方法设置一下
@Overridepublic 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;}

第四种使用scrollTo和scrollBy 会改变父布局内其他空间的布局
注意:scrollTo和scrollBy移动的是当前view的content,即让view的内容移动;如果在ViewGroup中使用scrollTo、scrollBy方法,那么移动的将是所有子View,如果在view中使用,那么移动的是view中的内容
形象的比喻一下,因为移动ViewGroup时坐标的变化是有些难理解的。即拿着放大镜去看书本上的字(书本和山面的字是不移动的),书本是固定的,要想让放大镜内的字往左下角移动,我们就应该让放大镜往右上角移动。ViewGroup其实就是放大镜,view就是书本上的字。
@Overridepublic 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类 会改变父布局内其他空间的布局
初始化Scroller
mScroller = new Scroller(context);
重写computeScroll()方法,实现模拟滑动
注意的是computeScroll()方法不会自动调用,所以在未执行完之前要通过ivalidate()到draw()再到computeScroll()来不断调用
@Overridepublic void computeScroll() {    super.computeScroll();    // 判断Scroller是否执行完毕    if (mScroller.computeScrollOffset()) {        ((View) getParent()).scrollTo(                mScroller.getCurrX(),                mScroller.getCurrY());        // 通过重绘来不断调用computeScroll        invalidate();    }}
mScroller.startScroll()开启模拟过程
@Overridepublic 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;}





1 0