Android贝塞尔曲线的简单应用之——实现仿美团点击商品掉落购物车效果,附demo和工具类

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_37717853/article/details/87879695

上一篇: Android贝塞尔曲线的简单应用之——实现自定义圆形控件内水波纹自动上升效果Demo

效果:

在这里插入图片描述

布局这里很简单,一个RecyclerView和一个ImageView,这里稍微注意下,ConstraintLayout等下我们要用到,所以这里加了id。

在这里插入图片描述

然后是在activity中设置recyclerview的adapter添加一些商品数据,在item的点击监听中调用封装好的工具类:BezierShopCarModule,传入指定参数,这样就可以实现商品掉落到购物车的效果了,是不是很easy?哈哈,下面来介绍下封装的类 BezierShopCarModule
/*设置监听*/
    private void setListener() {
        callBack = new CallBack() {
            @Override
            public void itemOnClickListener(View view,int position) {
                Log.i(TAG,"点击了第"+position+"个item");
                //实现贝塞尔曲线效果
                module = new BezierShopCarModule(clMain,view,ivShopCar);
                module.bezierCurveAnimation(MainActivity.this,800,R.mipmap.commodity_phone,view.getWidth(),view.getHeight());
            }
        };
    }

BezierShopCarModule 主要用到的方法就两个而已,构造方法如下,这里就要用到开头说的constraintlayout,传参的时候加上这个即可。
private ViewGroup layout;//布局文件,有标题栏的情况下,需获取内容布局的起始点坐标,后面的控件坐标减去该坐标才能得到准确坐标值,所以有无标题栏都减去这个值,避免出错
    private View startView;//起始点控件
    private View endView;//结束点控件

    /**
     * 构造方法
     * @param layout       布局文件,即xml文件的根布局layout,用于确定子view的相对位置
     * @param startView    曲线开始的控件
     * @param endView      曲线结束的控件(一般是”购物车“)
     */
    public BezierShopCarModule (ViewGroup layout, View startView, View endView){
        this.layout = layout;
        this.startView = startView;
        this.endView = endView;
    }
然后是实现动画效果的方法,下面有注释:
/**
     * 开启贝塞尔曲线动画效果
     * @param context           传入的view所在的activity的上下文变量
     * @param animationTime     动画执行时间
     * @param imageViewResource 图片资源
     * @param imageWidth         图片控件宽度
     * @param imageHeight        图片控件高度
     * @return                  执行结束,返回true
     */
    public boolean bezierCurveAnimation(Context context,int animationTime,int imageViewResource,int imageWidth,int imageHeight){
        //贝塞尔曲线,起始点
        int[] startPoint = new int[2];
        //贝塞尔曲线,结束点
        int[] endPoint = new int[2];
        //内容布局起始点,有标题栏的情况下,需获取内容布局的起始点坐标,后面的控件坐标减去该坐标才能得到准确坐标值,为确保准确,有无标题栏都减去该坐标
        int[] constraintLayoutPoint = new int[2];
        //获取坐标点
        layout.getLocationInWindow(constraintLayoutPoint);
        startView.getLocationInWindow(startPoint);
        endView.getLocationInWindow(endPoint);
        //赋值贝塞尔曲线用到的点
        PointF startF = new PointF();   //起始点
        PointF endF = new PointF();     //结束点
        PointF controllF = new PointF();//控制点

        startF.x = startPoint[0];
        startF.y = startPoint[1] - constraintLayoutPoint[1];//确定起始点Y坐标
        endF.x = endPoint[0]+(endView.getWidth()-imageWidth)/2;//使掉落的“商品”砸在“购物车”中间
        endF.y = endPoint[1] - constraintLayoutPoint[1];
        controllF.x = endF.x;
        controllF.y = startF.y;

        //创建控件
        final ImageView imageView = new ImageView(context);
        layout.addView(imageView);
        imageView.setImageResource(imageViewResource);//传入的图片资源
        imageView.getLayoutParams().width = imageWidth;//设置大小
        imageView.getLayoutParams().height = imageHeight;
        imageView.setVisibility(View.VISIBLE);
        imageView.setX(startF.x);
        imageView.setY(startF.y);

        //插值器
        ValueAnimator valueAnimator = ValueAnimator.ofObject(new BezierTypeEvaluator(controllF),startF,endF);
        //过程监听
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //获取曲线坐标
                PointF pointF = (PointF) valueAnimator.getAnimatedValue();
                //设置图片坐标
                imageView.setX(pointF.x);
                imageView.setY(pointF.y);
            }
        });
        //动画完成监听
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //移除控件
                layout.removeView(imageView);
            }
        });

        //购物车动画
        //属性动画,缩放
        ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(endView,"scaleX",0.8f,1.0f);
        ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(endView,"scaleY",0.8f,1.0f);
        //加速掉落
        objectAnimatorX.setInterpolator(new AccelerateInterpolator());
        objectAnimatorY.setInterpolator(new AccelerateInterpolator());
        //设置动画播放顺序
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(objectAnimatorX).with(objectAnimatorY).after(valueAnimator);
        //设置动画时长,启动
        animatorSet.setDuration(animationTime);
        animatorSet.start();
        return true;
    }
最后还有一个自定义的插值器,这是实现贝塞尔曲线的关键:
/**
     * Created by Given on 2019/2/22 0022.
     * 自定义插值器,用于实现贝塞尔曲线效果
     */
    public class BezierTypeEvaluator implements TypeEvaluator<PointF> {
        private PointF controllPoint;

        public BezierTypeEvaluator(PointF controllPoint){
            this.controllPoint = controllPoint;
        }

        @Override
        public PointF evaluate(float v, PointF startValue, PointF endValue) {

            PointF pointCur = new PointF();

            //基于二阶贝塞尔曲线公式,计算出曲线坐标点
            pointCur.x = (1-v)*(1-v)*startValue.x + 2*v*(1-v)*controllPoint.x + v*v*endValue.x;
            pointCur.y = (1-v)*(1-v)*startValue.y + 2*v*(1-v)*controllPoint.y + v*v*endValue.y;

            return pointCur;
        }
    }
以上就是这个封装的工具类里面用到的内容,用起来也很简单,方便以后移植到其它项目中。

Demo下载:https://download.csdn.net/download/qq_37717853/10970623

项目参考博客:https://www.cnblogs.com/wjtaigwh/p/6689684.html

猜你喜欢

转载自blog.csdn.net/qq_37717853/article/details/87879695