欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

安卓 实现滑动效果

程序员文章站 2022-07-14 12:54:03
...

实现滑动效果有下面几种方式

1.layout(int l, int t, int r, int b):

    1).参数:分别代表左上右下四个点的坐标    

    2).View绘制时,会通过onLayout方法设置显示位置,我们也可用通过layout函数调用onLayout方法

2.offsetLeftAndRight(int offset)与offsetTopAndBottom(int offset)

    1).参数:offset分别代表左右和上下的的偏移量

    2).这两个函数分别是同时对左右和上下偏移

3.scrollTo(int x, int y)

    1).参数:移动到(x,y) 坐标点

    scrollBy(int x, int y)

    1).参数:移动增量为dx,dy

    注意:

        1)scrollTo和scrollBy移动的是View的内容content,如果是TextView则移动文本,如果是ImageView则移动drawable

        2)这两者填写的参数都要为负值,图解如下

安卓 实现滑动效果

4.Scroller:实现了View从移动的过度动画,而不是一瞬间完成,其实scrollBy和scrollTo都是瞬间完成的,由于我们在ACTION_MOVE中不断获取手指位移量,所以看上去有过度效果

下面来分别实现

一、重写触摸事件

    要实现滑动、触摸等效果,都要重写触摸事件onTouchEvent

    几个获取坐标的方法:

View提供的方法

geTop:            得到View自身顶边到父布局顶边的距离

getBottom:     得到View自身底边到父布局顶边的距离

getLeft:           等到VIew自身左边到父布局左边的距离

getRight:        等到VIew自身右边到父布局左边的距离

MotionEvent提供的方法

getX:            得到点击事件距离View左边的距离,视图坐标

getY              得到点击事件距离View顶边的距离,视图坐标

getRawX        得到点击事件距离屏幕顶边的距离 ,绝对坐标     

getRawY:        得到点击事件距离屏幕顶边的距离,绝对坐标

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //得到当前坐标
        //视图坐标
        int x = (int)event.getX();
        int y = (int)event.getY();
        //绝对坐标
        int rawX = (int)event.getRawX();
        int rawY = (int)event.getRawY();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //记录按下的坐标点
                lastX = x;
                lastY = y;
                //lastX = rawX;
                //lastY = rawY;
                Log.e(TAG, "ACTION_DOWN: X="+x+";Y="+y );
                break;
            case MotionEvent.ACTION_MOVE:
                //用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
                //这样就得到了最新的偏移量
                int offsetX = x - lastX;
                int offsetY = y - lastY;
                //int offsetX = rawX - lastX;
                //int offsetY = rawY - lastY;
                //之后通过偏移量更新视图位置
                。。。下面介绍

                Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
                break;
            case MotionEvent.ACTION_UP:
                Toast.makeText(getContext(),"Up",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

二、实现移动

1.layout(int l, int t, int r, int b):

    更改上面代码:  

            case MotionEvent.ACTION_MOVE:
                //用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
                //这样就得到了最新的偏移量
                int offsetX = x - lastX;
                int offsetY = y - lastY;

                //之后通过偏移量更新视图位置
                layout(
                        getLeft() + offsetX,
                        getTop() + offsetY,
                        getRight() + offsetX,
                        getBottom() + offsetY
                );
                Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
                break;

2.offsetLeftAndRight(int offset)与offsetTopAndBottom(int offset)

    更改上面代码:

            case MotionEvent.ACTION_MOVE:
                //用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
                //这样就得到了最新的偏移量
                int offsetX = x - lastX;
                int offsetY = y - lastY;

                //同时对左右、上下移动
                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);

                Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
                break;

初始界面:

安卓 实现滑动效果

方法一二的效果一致:如下

安卓 实现滑动效果

当然同样也可以使用绝对坐标,不过要注意绝对坐标中,要在ACTION_MOVE中重置初始坐标

代码:

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        //得到当前坐标
        //视图坐标
        int x = (int)event.getX();
        int y = (int)event.getY();
        //绝对坐标
        int rawX = (int)event.getRawX();
        int rawY = (int)event.getRawY();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //记录按下的坐标点
                lastX = rawX;
                lastY = rawY;
                Log.e(TAG, "ACTION_DOWN: X="+x+";Y="+y );
                break;
            case MotionEvent.ACTION_MOVE:
                //用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
                //这样就得到了最新的偏移量
                int offsetX = rawX - lastX;
                int offsetY = rawY - lastY;
                //之后通过偏移量更新视图位置
                //同时对左右、上下移动
                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);

                //更新初始坐标
                lastX = rawX;
                lastY = rawY;
                Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
                break;
            case MotionEvent.ACTION_UP:
                Toast.makeText(getContext(),"Up",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

3.scrollTo(int x, int y)和scrollBy

    这个就不一样了,因为移动的是内容

    更改代码如下:View内容移动

            case MotionEvent.ACTION_MOVE:
                //用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
                //这样就得到了最新的偏移量
                int offsetX = x - lastX;
                int offsetY = y - lastY;

                //View的内容移动
                scrollTo(-offsetX,-offsetY);
                Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
                break;

效果:

安卓 实现滑动效果

更改代码如下:View父布局移动

            case MotionEvent.ACTION_MOVE:
                //用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
                //这样就得到了最新的偏移量
                int offsetX = x - lastX;
                int offsetY = y - lastY;

                //移动View的父布局
                ((View)getParent()).scrollBy(-offsetX,-offsetY);

                Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
                break;

效果:

安卓 实现滑动效果

4.Scroller:实现过渡动画,在ACTION_UP中实现抬起手指,控件自己返回的效果

1)首先实例化Scroller

scroller = new Scroller(context);

2)重写computeScroll

    系统在绘制View的draw方法中会调用这个方法

    重写computeScroll实现模拟移动

    @Override
    public void computeScroll() {
        super.computeScroll();
        //判断Scrolle是否执行完毕
        if (scroller.computeScrollOffset()){
            ((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
            //重绘
            invalidate();
        }
    }

computeScrollOffset:    判断是否完成了整个滑动

getCurrX:                    得到当前的互动坐标X

getCurrY:                    得到当前的互动坐标Y

由于computeScroll不会自己调用,所以需要invalidate来实现从invalidate->draw->computeScroll的间接调用

3)开始模拟滑动

startScroll(int startX, int startY, int dx, int dy, int duration) :

参数:(startX,startY)起始坐标,dx,dy分别是x轴和y轴的偏移量,最后是滑动完成的时间,可以省略

在ACTION_UP中开始,实现手指抬起,View返回原坐标位置

            case MotionEvent.ACTION_UP:
                Toast.makeText(getContext(),"Up",Toast.LENGTH_SHORT).show();
                View view = ((View)getParent());
                scroller.startScroll(
                        view.getScrollX(),
                        view.getScrollY(),
                        -view.getScrollX(),
                        -view.getScrollY(),
                        3000
                );
                invalidate();
                break;

invalidate();发出重绘信号

效果;

安卓 实现滑动效果