【Android】加入购物车赛贝尔曲线动画效果

public class Anim {


    private final long durationTime = 500;//动画持续时间


    /**
     * 添加商品到购物车的动画效果
     *
     * @param goodsImg       进行于移动的商品图片就是列表里商品图片
     * @param relativeLayout 页面父布局
     * @param shoppingCarImg 购物车图片
     */
    public void addGoodsToCart(Context context, ImageView goodsImg, RelativeLayout relativeLayout, ImageView shoppingCarImg, String productImageUrl) {


        //这里用superTextView承载一个圆形的图片
        final SuperTextView goods = new SuperTextView(context);
        goods.setUrlImage(productImageUrl);
        goods.setCorner(50);//设置圆角
        goods.setStrokeColor(Color.RED);//边框颜色
        goods.setStrokeWidth(4);//边框宽度


        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(68, 68);
        relativeLayout.addView(goods, params);

        //父布局起始坐标
        int[] parentLocation = new int[2];
        relativeLayout.getLocationInWindow(parentLocation);

        //得到商品的图片坐标
        int startLoc[] = new int[2];
        goodsImg.getLocationInWindow(startLoc);

        //购物车图片坐标
        int endLoc[] = new int[2];
        shoppingCarImg.getLocationInWindow(endLoc);


        //开始掉落的商品的起始点:
        //简单来说就是该商品图片的中心点
        float startX = startLoc[0] - parentLocation[0];
        float startY = startLoc[1] - parentLocation[1];

        // 商品掉落后的终点坐标:购物车起始点-父布局起始点
        float toX = endLoc[0] - parentLocation[0];
        float toY = endLoc[1] - parentLocation[1];

        //绘制贝塞尔曲线
        Path path = new Path();
        //路径移动到起始点
        path.moveTo(startX, startY);
        // 使用二阶贝塞尔曲线:注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大
        path.quadTo((startX + toX) / 2, startY, toX, toY);

        //用来计算贝塞尔曲线的曲线长度和贝塞尔曲线中间插值的坐标,如果是true,path会形成一个闭环
        PathMeasure pathMeasure = new PathMeasure(path, false);

        // 属性动画实现(从0到贝塞尔曲线的长度之间进行插值计算,获取中间过程的距离值)
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, pathMeasure.getLength());
        valueAnimator.setDuration(durationTime);//图片持续时间


        // 贝塞尔曲线中间过程点坐标
        float[] currentPosition = new float[2];

        // 加速插值器
        valueAnimator.setInterpolator(new AccelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 当插值计算进行时,获取中间的每个值,
                // 这里这个值是中间过程中的曲线长度(下面根据这个值来得出中间点的坐标值)
                float value = (Float) animation.getAnimatedValue();
                // 获取当前点坐标封装到currentPosition
                // boolean getPosTan(float distance, float[] pos, float[] tan) :
                // 传入一个距离distance(0<=distance<=getLength()),然后会计算当前距离的坐标点和切线,pos会自动填充上坐标,这个方法很重要。
                // currentPosition此时就是中间距离点的坐标值
                pathMeasure.getPosTan(value, currentPosition, null);
                // 移动的商品图片(动画图片)的坐标设置为该中间点的坐标
                goods.setTranslationX(currentPosition[0]);
                goods.setTranslationY(currentPosition[1]);
            }
        });


        // 开始执行动画
        valueAnimator.start();
        valueAnimator.setStartDelay(500);//动画延迟执行时间

        // 动画结束后的处理
        valueAnimator.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                onAddGoodsToCartListener.start();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //这里可以拿出接口,写购物车的变化
                LogUtils.d("动画效果结束");
                relativeLayout.removeView(goods);//移除移动的图片

                onAddGoodsToCartListener.end();
            }
        });

    }


    public interface OnAddGoodsToCartListener {
        void start();

        void end();
    }

    private OnAddGoodsToCartListener onAddGoodsToCartListener;

    public void setOnAddGoodsToCartListener(OnAddGoodsToCartListener onAddGoodsToCartListener) {
        this.onAddGoodsToCartListener = onAddGoodsToCartListener;
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容