Android 属性动画 移动到指定坐标

Android 属性动画 移动到指定坐标_第1张图片

1.简单

 //将View 移动到(100,100)点

        final float x = view.getX();
        final float y = view.getY();

        final int targetX = 100;
        final int targetY = 100;

        // 第一种 无法改变 路径
        view.animate()
                .translationX(-(x - targetX))
                .translationY(-(y - targetY))
                .setDuration(2000)
                .setInterpolator(new AccelerateInterpolator())
                .withLayer()
                .start();


2.复杂

ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setDuration(2000);
        valueAnimator.setObjectValues(new PointF(x, y));
        valueAnimator.setInterpolator(new LinearInterpolator());


        //首先判断 目标点在上还是在下

        final boolean flagX = ((x - targetX) > 0) ? true : false;
        final boolean flagY = ((y - targetY) > 0) ? true : false;


        valueAnimator.setEvaluator(new TypeEvaluator() {

            @Override
            public PointF evaluate(float fraction, PointF startValue,
                                   PointF endValue) {
                //从0.0 --->>   1.0
//                System.out.println(" fraction :" + fraction);

                PointF point = new PointF();
                //这里是需要倒着来  最后要到达200 200 这个点

                float fractionNeed = 1 - fraction;

                if (flagX) {
                    float vX = x - targetX;
                    point.x = vX * fractionNeed + targetX;
                } else {
                    float vX = targetX - x;
                    point.x = x + vX * fraction;
                }

                if (flagY) {
                    float vY = y - targetY;
                    point.y = vY * fractionNeed + targetY;
                } else {
                    float vY = targetY - y;
                    point.y = y + vY * fraction;
                }
                return point;

            }
        });

        valueAnimator.start();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                PointF point = (PointF) animation.getAnimatedValue();
                float vX = point.x;
                float vY = point.y;
                //说明vx 最大值就是view原坐标
                if (flagX) {
                    if (vX <= x && vX >= targetX) {
                        view.setX(vX);
                    }
                } else {//说明vx 最小值就是view原坐标
                    if (vX >= x && vX <= targetX) {
                        view.setX(vX);
                    }
                }

                //说明vY 最大值就是view原坐标
                if (flagY) {
                    if (vY <= y && vY >= targetY) {
                        view.setY(vY);
                    }
                } else {//说明vx 最小值就是view原坐标
                    if (vY >= y && vY <= targetY) {
                        view.setY(vY);
                    }
                }

            }
        });

Android 属性动画 移动到指定坐标_第2张图片

加点 弯曲效果

                //要让他有抛物线的感觉 那就改其中一个轴
                if (flagY) {
                    float vY = y - targetY;
//                    point.y = (vY * fractionNeed + targetY) * (1 + fractionNeed * fractionNeed);
                    if (fractionNeed > 0.5) {
                        point.y = vY * fractionNeed * fractionNeed + targetY;
                    } else {
                        point.y = vY * fractionNeed * (1 - fractionNeed) + targetY;

                    }
                } else {
                    float vY = targetY - y;
//                    point.y = (y + vY * fraction) * (1 + fraction * fractionNeed);
                    point.y = y + vY * fraction * fraction;
                }

最直接的是在

onAnimationUpdate 方法中 setX,setY时直接*int;无法控制到达指定坐标点

3.可用于购物车

 

Android 属性动画 移动到指定坐标_第3张图片

XML




    

    

2.main

private ImageView imageEnd;
    private float[] mCurrentPosition = new float[2];
    private RelativeLayout parent;
    private ImageView imageStart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageStart = findViewById(R.id.imageStart);
        imageEnd = findViewById(R.id.imageEnd);
        parent = findViewById(R.id.parent);


    }

    public void move(final View view) {

        final ImageView imageView = new ImageView(this);
        imageView.setImageDrawable(imageStart.getDrawable());

        parent.addView(imageView, 80, 80);

        int[] parentLoc = new int[2];
        parent.getLocationInWindow(parentLoc);

        //将View 移动到(100,100)点

        int[] startLoc = new int[2];
        view.getLocationInWindow(startLoc);


        int[] endLoc = new int[2];
        imageEnd.getLocationInWindow(endLoc);

        //开始掉落的商品的起始点:商品起始点-父布局起始点+该商品图片的一半
        float startX = startLoc[0] - parentLoc[0]+view.getWidth()/2;
        float startY = startLoc[1] - parentLoc[1]+view.getWidth()/2;

        //商品掉落后的终点坐标:购物车起始点-父布局起始点+购物车图片的1/5
        float toX = endLoc[0] - parentLoc[0] + imageEnd.getWidth() / 2;
        float toY = endLoc[1] - parentLoc[1] + imageEnd.getHeight() / 2;

        Path path = new Path();
        //移动到起始点(贝塞尔曲线的起点)
        path.moveTo(startX, startY);

        //使用二次萨贝尔曲线:注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大,一般按照下面的式子取即可
        path.quadTo((startX + toX) / 2+200, startLoc[1], toX, toY);
        //mPathMeasure用来计算贝塞尔曲线的曲线长度和贝塞尔曲线中间插值的坐标,
        // 如果是true,path会形成一个闭环
        final PathMeasure mPathMeasure = new PathMeasure(path, false);

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());
        valueAnimator.setDuration(1000);

        // 匀速线性插值器
        valueAnimator.setInterpolator(new BounceInterpolator());

        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 当插值计算进行时,获取中间的每个值,
                // 这里这个值是中间过程中的曲线长度(下面根据这个值来得出中间点的坐标值)
                float value = (Float) animation.getAnimatedValue();

                //mCurrentPosition此时就是中间距离点的坐标值
                mPathMeasure.getPosTan(value, mCurrentPosition, null);

                // 移动的商品图片(动画图片)的坐标设置为该中间点的坐标
                imageView.setTranslationX(mCurrentPosition[0]);
                imageView.setTranslationY(mCurrentPosition[1]);
            }
        });
        valueAnimator.start();

    }
imageStart.setVisibility(View.GONE);
imageEnd.setVisibility(View.GONE);

直接隐藏就会有那种单身狗的赶脚了.

 

 

 

你可能感兴趣的:(学习ing)