安卓自定义view仿小米商城购物车动画

Posted yuhongmiao521

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓自定义view仿小米商城购物车动画相关的知识,希望对你有一定的参考价值。

通过自定义View与ViewGroup实现小米商城购物车效果

用到的知识点

  1. 自定义View
  2. 自定义ViewGroup
  3. 贝塞尔曲线

原理

  • 通过贝塞尔曲线实现商品抛入购物车的路径
  • 自定义ViewGroup实现添加多个商品进购物车的动画
  • 自定义View绘制心以及购物车图案

代码

一.绘制底部背景View

1.通过Path绘制第一部分,绘制心以及文字
通过贝赛尔曲线绘制心形

/**
     * 绘制喜欢
     *
     * @param canvas
     * @param x
     * @param y
     */
    private void drawLove(Canvas canvas, float x, float y) 
        canvas.save();
        canvas.translate(x, y);
        Path leftPath = new Path();
        leftPath.moveTo(0, -40);
        Path rightPath = new Path();
        rightPath.moveTo(0, -40);
        leftPath.cubicTo(0, -40, -30, -80, -35, -40);
        leftPath.cubicTo(-35, -40, -30, -30, 0, 10);
        rightPath.cubicTo(0, -40, 30, -80, 35, -40);
        rightPath.cubicTo(35, -40, 30, -30, 0, 10);

        if (isLove) 
            mLovePaint.setStyle(Paint.Style.FILL);
            mLovePaint.setColor(Color.RED);
         else 
            mLovePaint.setStyle(Paint.Style.STROKE);
            mLovePaint.setColor(Color.BLACK);
        

        mLovePaint.setStrokeWidth(3);
        canvas.drawPath(leftPath, mLovePaint);
        canvas.drawPath(rightPath, mLovePaint);
        canvas.restore();

        float measureText = mTextPaint.measureText("喜欢", 0, "喜欢".length());

        canvas.drawText("喜欢", x - measureText / 2, y + 50, mTextPaint);
    

2.绘制购物车区域 绘制购物车图形以及文购物车文字
通过Path的拼接绘制购物车图形

 /**
     * 绘制购物车
     *
     * @param canvas
     * @param x
     * @param y
     */
    private void drawShoppingCart(Canvas canvas, float x, float y) 
        canvas.save();
        canvas.translate(x, y);
        Path mPath = new Path();
        mPath.moveTo(-40, -60);
        mPath.lineTo(-30, -60);
        mPath.lineTo(-20, 0);
        mPath.lineTo(20, 0);
        mPath.lineTo(30, -40);
        mPath.lineTo(-10, -40);
        Path mPath2 = new Path();
        mPath2.moveTo(-10, -25);
        mPath2.lineTo(10, -25);

        mShoppingCartPaint.setStyle(Paint.Style.STROKE);
        mShoppingCartPaint.setStrokeWidth(5);
        mShoppingCartPaint.setColor(Color.BLACK);
        canvas.drawPath(mPath, mShoppingCartPaint);
        canvas.drawPath(mPath2, mShoppingCartPaint);
        mShoppingCartPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(-15, 10, 5, mShoppingCartPaint);
        canvas.drawCircle(15, 10, 5, mShoppingCartPaint);
        mShoppingCartPaint.setColor(Color.RED);
        canvas.drawCircle(30, -40, 20, mShoppingCartPaint);

        String strNum = mProductTotal + "";
        mTextPaint.setTextSize(20);
        mTextPaint.setColor(Color.WHITE);
        float strNumLength = mTextPaint.measureText(strNum, 0, strNum.length());
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();

        canvas.drawText(strNum, 30 - strNumLength / 2, -40 - (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.top, mTextPaint);
        canvas.restore();
        String str = "购物车";

        mTextPaint.setTextSize(30);
        mTextPaint.setColor(Color.BLACK);
        float measureText = mTextPaint.measureText(str, 0, str.length());
        canvas.drawText(str, x - measureText / 2, y + 50, mTextPaint);

    

3.绘制加入购物车文字
通过FontMetrics实现文字在矩形中心居中对齐

/**
     * 绘制加入购物车购物车
     *
     * @param canvas
     * @param x
     * @param y
     */
    private void drawShoppingText(Canvas canvas, float x, float y) 
        String str = "加入购物车";
        TextPaint textPaint = new TextPaint();
        textPaint.setTextSize(50);
        float measureText = textPaint.measureText(str, 0, str.length());
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        float v = fontMetrics.bottom - fontMetrics.top;
        canvas.drawText(str, x - measureText / 2, y - v / 2 - fontMetrics.top, textPaint);
    

二.绘制动画View

1.绘制商品图片在抛物线路径上,抛物线路径由贝塞尔曲线组成,通过不断的改变数值实现商品图片抛物线移动

/**
     * 绘制商品图片在抛物线路径上
     * @param canvas
     */
    private void drawProductOnPath(Canvas canvas) 
        PointF mCurveStart = new PointF();//曲线开始的点
        PointF mCurveMiddle = new PointF();//曲线中间点
        PointF mCurveEnd = new PointF();//曲线结束的点
        mCurveStart.set(measuredWidth * 0.7f, measuredHeight - 85);
        mCurveMiddle.set(measuredWidth * 0.4f, 0);
        mCurveEnd.set(measuredWidth * 0.3f, measuredHeight - 85);
        Path mCurvePath = new Path();//移动曲线
        mCurvePath.moveTo(mCurveStart.x, mCurveStart.y);
        mCurvePath.cubicTo(mCurveStart.x, mCurveStart.y, mCurveMiddle.x, mCurveMiddle.y, mCurveEnd.x, mCurveEnd.y);
        PathMeasure pathMeasure = new PathMeasure();
        pathMeasure.setPath(mCurvePath, false);
        float[] pos = new float[2];
        pathMeasure.getPosTan(pathMeasure.getLength() * percent, pos, null);
        Matrix matrix = new Matrix();
        matrix.postTranslate(pos[0] - newBitmap.getWidth() / 2, pos[1] - newBitmap.getHeight() / 2);
        canvas.drawBitmap(newBitmap, matrix, mBitmapPaint);
    

2.ValueAnimator 数值改变的同时从绘View,实现商品图片的抛入购物车的动画效果,当View添加的时候start此ValueAnimator

/**
     * 改变数值实现动画
     */
    private void initAnimator() 
        valueAnimator = ValueAnimator.ofInt(ints);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() 
            @Override
            public void onAnimationUpdate(ValueAnimator animation) 
                int animatedValue = (int) animation.getAnimatedValue();
                percent = animatedValue / 100f;
                if (percent < 0.8) 
                    int height = (int) (bitmapWidth * (1 - percent));
                    int width = (int) (bitmapHeight * (1 - percent));
                    if (width > 0 && height > 0) 
                        newBitmap = scaleBitmap(bitmap, 1 - percent);
                    
                
                invalidate();
            
        );
        valueAnimator.addListener(new AnimatorListenerAdapter() 
            @Override
            public void onAnimationEnd(Animator animation) 
                super.onAnimationEnd(animation);
                mBitmapPaint.setAlpha(0);
            

            @Override
            public void onAnimationStart(Animator animation) 
                super.onAnimationStart(animation);
                mBitmapPaint.setAlpha(255);
            
        );
        valueAnimator.setDuration(500);
        valueAnimator.setInterpolator(new AccelerateInterpolator());

    

自定义ViewGroup实现购物车效果

1.ViewGroup初始化的时候将底部背景View添加进ViewGroup并且Layout的在底部
2.当点击加入购物车时候,将动画View添加进此ViewGroup,并且启动动画绘制界面实现商品抛进购物车效果。

@Override
    public void add(int mProductTotal) 
        if (shoppingCartListener != null) 
            shoppingCartListener.add(mProductTotal);
        
        ShoppingAnimChildView shoppingAnimView = new ShoppingAnimChildView(getContext());
        if (mProductBitmap != null) 
            shoppingAnimView.setProductBitmap(mProductBitmap);
        
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        addView(shoppingAnimView, layoutParams);

        requestLayout();
        shoppingAnimView.startAnim();

    

详细代码见Github传送门
欢迎大家star,fork
有很多不足,望见谅

可以直接下载代码使用

使用方法如下

使用方法

1.布局文件添加以下属性

<com.yhongm.shoppingcart.ShoppingCartView

android:id="@+id/vg"

android:layout_alignParentBottom="true"

android:layout_width="match_parent"

android:layout_height="300dp" />

2.java方法:

scvg.setProductBitmap(产品图片bitmap); 设置产品图片

scvg.setShoppingCartListener(this); 设置点击监听

以上是关于安卓自定义view仿小米商城购物车动画的主要内容,如果未能解决你的问题,请参考以下文章

仿小米商城的首页

小程序之仿小米商城Lite

50自定义View练习高仿小米时钟-使用Camera和Matrix实现3D效果

商城项目实战 | 2.2 Android 仿京东商城——自定义 Toolbar

Android自定义View实战之仿百度加载动画,一种优雅的Loading方式

Android自定义View实战之仿百度加载动画,一种优雅的Loading方式