安卓 实现滑动效果

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

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();发出重绘信号

效果;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Amarao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值