Android实现滑动的几种方法

参考文章转自:https://blog.csdn.net/shakespeare001/article/details/51657795

文章说了5种方式的滚动方法,说的都没啥毛病。但是OnTouchEvent方法没有说清楚,我想了一阵子之后明白其中的道理

 @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mLastX = x;
                mLastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                //调整layout的四个坐标
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);

                int left=getLeft();
                Log.v("xhw","left:"+left+" x:"+x  +" mLastX:"+mLastX+ " offsetX:"+offsetX);
                break;
        }
        return true;
    }

我们view的样式如图,当我们点击这个view的时候,会触发OnTouchEvent方法。而这个坐标

int x = (int) ev.getX();
int y = (int) ev.getY();

是指我们蓝色view中的坐标,(0,0)是蓝色view的左上角的位置。当点击view的时候出发如下ACTION_DOWN

 case MotionEvent.ACTION_DOWN:
                mLastX = x;
                mLastY = y;

这个x和y是蓝色view上面的坐标,而不是屏幕上的坐标。

当出发滑动事件的时候:

方法1、layout

int offsetX = x - mLastX;
int offsetY = y - mLastY;
//调整layout的四个坐标
layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);

这里是关键了啊,当我们手指滑动得时候,会在蓝色得view上滑动,那么就会产生一个滑动得距离。我们通过计算滑动距离之后,通过layout方法设置我们得位置,并且给这个位置添加移动的偏移量。这样我们的蓝色view就跟着手指移动了,手指点击的位置又回到了我们mLastX以及mLastY的位置。形象点来说 我们的视图view跟上来了!

需要注意的是我们layout方法改变的是这个view的getLeft、getRight等属性。

方法2、offsetLeftAndRight以及 offsetTopAndBottom

  int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                //调整layout的四个坐标
                //layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
                //使用简写形式
                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);

都是改变的view的left、right、top、bottom的属性的。我们第二种移动方法原理跟这个是一样的。

 

方法3、margin值

case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                ViewGroup.MarginLayoutParams  lp = (ViewGroup.MarginLayoutParams ) getLayoutParams();
                lp.leftMargin = getLeft() + offsetX;
                lp.topMargin = getTop() + offsetY;
                setLayoutParams(lp);
                break;

设置view的距离也可以通过margin去影响

方法4、scrollBy

case MotionEvent.ACTION_MOVE:
                //int offsetX = x - mLastX;
                //int offsetY = y - mLastY;
                //此时,计算坐标是相反的
                int offsetX = mLastX - x;
                int offsetY = mLastY - y;
                //让View所在的ViewGroup进行移动
                ((View)getParent()).scrollBy(offsetX,offsetY);
                break;

这个是通过父类容器的scrollBy方法来移动我们的试图,这个不会改变view本身的属性,而是通过滑动视窗的方式

方法5、Scroller

这种方式好像没啥用,Scroller是为了计算用的 滑动最终还是通过scrollBy或者scrollTo方法

 

文章把这几种方式都介绍完了,但是偏偏忘记了另一种方式setTranslateX以及setTranslateY的方法,我们属性动画都是通过改变translateX这种方式。

我们view的坐标X=left+translateX。我们上面的动画已经使用了left的方式,那么还可以通过translateX方式

方法6:setTranslateX

public class DragView5 extends View {

    private int mLastX;
    private int mLastY;

    private int cumulativeX;
    private int cumulativeY;

    public DragView5(Context context) {
        super(context);
        init();
    }

    public DragView5(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DragView5(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init(){
        setBackgroundColor(Color.BLUE);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mLastX = x;
                mLastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                cumulativeX+=offsetX;
                cumulativeY+=offsetY;

                setTranslationX(cumulativeX);
                setTranslationY(cumulativeY);

                int left=getLeft();
                float translateX=getTranslationX();
                Log.v("xhw","left:"+left+" translateX:"+translateX);
                break;
        }
        return true;
    }
}

我们参数值每次设置都会把之前的距离覆盖掉,所以我通过cumulativeX以及cumulativeY去累计我们移动的距离

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值