android三种方式实现自由移动的view

描述

实现一个可以在父容器中随着手指自由移动的view

思路

1.继承view,重写onTouchEvent()方法
2.通过getX(),getY()方法获取新的位置
3.将控件移动到当前位置
4.继承View实现感觉更高大上,这里继承ImageView是为了设置背景方便观察

实战

1.通过setX(),setY()来重新设置view的位置

public class MoveView extends ImageView {
    private int x, y;

    public MoveView(Context context) {
        this(context, null);
    }

    public MoveView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int) event.getX();
        y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                AnimatorSet setDown = new AnimatorSet();
                setDown.playTogether(
                        ObjectAnimator.ofFloat(this, "scaleX", 1f, 1.5f),
                        ObjectAnimator.ofFloat(this, "scaleY", 1f, 1.5f),
                        ObjectAnimator.ofFloat(this, "alpha", 1f, 0.5f)
                );
                setDown.start();
                break;
            case MotionEvent.ACTION_MOVE:
                //个人感觉跟手时,指尖在控件的中间比较好,所以减去宽高的一半
                setX(x + getLeft() + getTranslationX() - getWidth() / 2);
                setY(y + getTop() + getTranslationY() - getHeight() / 2);
                break;
            case MotionEvent.ACTION_UP:
                AnimatorSet setUp = new AnimatorSet();
                setUp.playTogether(
                        ObjectAnimator.ofFloat(this, "scaleX", 1.5f, 1f),
                        ObjectAnimator.ofFloat(this, "scaleY", 1.5f, 1f),
                        ObjectAnimator.ofFloat(this, "alpha", 0.5f, 1f)
                );
                setUp.start();
                break;
        }

        return true;
    }
}
在view按下时添加了动画。滑动时跟手的感觉很强,实现简洁。

2.通过layout()来重新设置view的位置

public class MoveView extends ImageView {
    private int x, y;
    private int r, l, t, b;

    public MoveView(Context context) {
        this(context, null);
    }

    public MoveView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int) event.getX();
        y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                AnimatorSet setDown = new AnimatorSet();
                setDown.playTogether(
                        ObjectAnimator.ofFloat(this, "scaleX", 1f, 1.5f),
                        ObjectAnimator.ofFloat(this, "scaleY", 1f, 1.5f),
                        ObjectAnimator.ofFloat(this, "alpha", 1f, 0.5f)
                );
                setDown.start();
                break;
            case MotionEvent.ACTION_MOVE:
                l = (int) (x + getTranslationX() - getWidth() / 2 + getLeft());
                t = (int) (y + getTranslationY() - getHeight() / 2 + getTop());
                r = l + getWidth();
                b = t + getHeight();
                layout(l,t,r,b);
                break;
            case MotionEvent.ACTION_UP:
                AnimatorSet setUp = new AnimatorSet();
                setUp.playTogether(
                        ObjectAnimator.ofFloat(this, "scaleX", 1.5f, 1f),
                        ObjectAnimator.ofFloat(this, "scaleY", 1.5f, 1f),
                        ObjectAnimator.ofFloat(this, "alpha", 0.5f, 1f)
                );
                setUp.start();
                break;
        }

        return true;
    }
}

原理跟第一种方式差不多。滑动时跟手的感觉很强,代码多几行。

3.属性动画

public class MoveView extends ImageView {
    private int x, y;
    private int r, l, t, b;

    public MoveView(Context context) {
        this(context, null);
    }

    public MoveView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int) event.getX();
        y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                AnimatorSet setDown = new AnimatorSet();
                setDown.playTogether(
                        ObjectAnimator.ofFloat(this, "scaleX", 1f, 1.5f),
                        ObjectAnimator.ofFloat(this, "scaleY", 1f, 1.5f),
                        ObjectAnimator.ofFloat(this, "alpha", 1f, 0.5f)
                );
                setDown.start();
                break;
            case MotionEvent.ACTION_MOVE:
                l = (int) (x + getTranslationX() - getWidth() / 2 + getLeft());
                t = (int) (y + getTranslationY() - getHeight() / 2 + getTop());
                ObjectAnimator.ofFloat(this, View.TRANSLATION_X, l).start();
                ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, t).start();
                break;
            case MotionEvent.ACTION_UP:
                AnimatorSet setUp = new AnimatorSet();
                setUp.playTogether(
                        ObjectAnimator.ofFloat(this, "scaleX", 1.5f, 1f),
                        ObjectAnimator.ofFloat(this, "scaleY", 1.5f, 1f),
                        ObjectAnimator.ofFloat(this, "alpha", 0.5f, 1f)
                );
                setUp.start();
                break;
        }

        return true;
    }
}
跟手感差,3.0后才能使用

总结

1.scrollTo只能对view的内容滑动,不适应当前继承View的场景
2.ViewDragHelper实现也可,代码就不贴了
3.也可以通过继承ViewGroup实现对子view的自由移动


你可能感兴趣的:(自定义view)