Android动画--移动View的几种方式

— Android群英传读书笔记

概述


View位置的变化和触控操作都涉及到MotionEvent类,MotionEvent中封装了一些与触摸相关的东西,比如触摸事件Action,触摸坐标等。移动View无疑就是改变其位置,通常有以下几种方式。

layout


View 类中,我们知道有一个layout方法是给View定位的 ,结合onTouchEvent方法 ,我们可以很好的实现一个View的移动.

int lastX, lastY;

    @Override
    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;

                 layout(getLeft()+offsetX,
                 getTop()+offsetY,
                 getRight()+offsetX,
                 getBottom()+offsetY);

                lastX = rawX;
                lastY = rawY;

                break;
        }

        return true;
    }

这里面使用了绝对坐标,使用绝对坐标的时候,需要在每次ACTION_MOVE后重新设置初始坐标.

offsetLeftAndRight()


使用offsetLeftAndRight();offsetTopAndBottom();方法,通过设置偏移量来滑动View


    int lastX, lastY;

    @Override
    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;

                //layout(getLeft()+offsetX,
                // getTop()+offsetY,
                // getRight()+offsetX,
                // getBottom()+offsetY);

                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);
                lastX = rawX;
                lastY = rawY;

                break;
        }

        return true;
    }

过offset值改变View的getTop()、getBottom(),getRight(),getLeft()的值

LayoutParams


LayoutParams,使用LayoutParams滑动View,通过改变布局参数来达到滑动View的目的.

 int lastX, lastY;

    @Override
    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;

                // layout(getLeft()+offsetX,
                // getTop()+offsetY,
                // getRight()+offsetX,
                // getBottom()+offsetY);

//                offsetLeftAndRight(offsetX);
//                offsetTopAndBottom(offsetY);

                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
                layoutParams.leftMargin = getLeft() + offsetX ;
                layoutParams.topMargin = getTop() +offsetY;
                setLayoutParams(layoutParams);

                lastX = rawX;
                lastY = rawY;

                break;
        }

        return true;
    }

ScrollTo() ScrollBy()


使用ScrollTo() 和ScrollBy() 方法来改变View 的位置.


    int lastX, lastY;

    @Override
    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;

                // layout(getLeft()+offsetX,
                // getTop()+offsetY,
                // getRight()+offsetX,
                // getBottom()+offsetY);

//                offsetLeftAndRight(offsetX);
//                offsetTopAndBottom(offsetY);

//                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
//                layoutParams.leftMargin = getLeft() + offsetX ;
//                layoutParams.topMargin = getTop() +offsetY;
//                setLayoutParams(layoutParams);

                ((View) getParent()).scrollBy( -offsetX, -offsetY);

                lastX = rawX;
                lastY = rawY;

                break;
        }

        return true;
    }

这里需要注意的是
1.首先我们的ScrollTo() and ScrollBy()方法移动的是View的Content
2.我们移动的是画布,因此需要设置相反的值,才能让View 跟随手指移动.

Scroller


使用Scroller类来移动View,与ScrollBy()方法关系紧密,ScrollBy()移动是瞬时完成,Scroller类在ACTION_MOVE中对偏移量进行划分,达到平滑效果.我们需要三个步骤.

 mScroller = new Scroller(context);
@Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            ((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }
 case MotionEvent.ACTION_UP:

                ViewGroup viewGroup = (ViewGroup) getParent();         mScroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY());

                invalidate();

                break;

computeScroll判断是否滑动结束,进而进行滑动,之后通过invalidate()刷新界面调用onDraw方法

Property Animation


通过 属性动画对View位置对改变

        int w = text.getWidth();
        int screenW = UiUtil.getScreenWidth();
        int transX = screenW - w;
        ObjectAnimator transAnim = ObjectAnimator.ofFloat(text, "translationX", 0, transX);

ViewDragHelper


使用v4包中的ViewDragHelper能很好的实现View的滑动和事件分发,典型谷歌官方的 Drawerlayout

ViewDragHelper封装了滚动操作,其内部使用了Scroller,关于ViewDragHelper的介绍网上也很多,重要的就是其内部类ViewDragHelper.callback,我们只需要按需复写即可.

实例:ViewDragHelper实现QQ侧滑效果DragLayout[github]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值