android自定义view之星星动画

先上效果图
在这里插入图片描述
其实上边效果分为几个部分,一个部分是多个小星星四处扩散,第二个部分是一个小星星从小变大,还有一个是实心圆的动画。
代码如下

第一:所有的小星星动画


public class StarView extends View {

    private Paint mPaint;

    private Bitmap mStar;							// 星星图片

    private ArrayList<StarModel> mStarModelList	= null;

    private float					mCurrentProgress;				// 当前进度

    private int						mCenterX, mCenterY;				// 中心点

    private ValueAnimator mValueAnimator;

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

    public StarView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        mStar = BitmapFactory.decodeResource(getResources(), R.mipmap.stars1);
    }

    @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mCenterX = getMeasuredWidth() / 2 - mStar.getWidth() / 2; // 90
        mCenterY = getMeasuredHeight() / 2 - mStar.getHeight() / 2; // 90
    }

    @Override protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mStarModelList == null) {
            return;
        }
        for (StarModel starModel : mStarModelList) {
            starModel.draw(canvas, mPaint, mCurrentProgress, mCenterX, mCenterY);
        }
    }

    public ValueAnimator startAnimation(int length, int duration, int delay) {
        if (mStarModelList != null) {
            mStarModelList.clear();
            mValueAnimator = null;
        }
        initStarModel(length);

        mValueAnimator = ValueAnimator.ofFloat(0f, 1f);
        mValueAnimator.setInterpolator(new DecelerateInterpolator());
        mValueAnimator.setDuration(duration);

        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentProgress = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        mValueAnimator.setStartDelay(delay);
        mValueAnimator.start();
        return mValueAnimator;
    }

    private void initStarModel(int length) {
        mStarModelList = new ArrayList<>(10);
        Random random = new Random();

        for (int i = 0; i < length; i++) {
            float angle = 0f;
            float startX = 0f;
            float startY = 0f;
            float speed = 1 + random.nextInt(5); // 总共是19

            float scale = 1f; // 开始大小

            if (i == 0) {
                angle = (float) ((10 + 270) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.05f;
                startY = (float) Math.sin(angle) * mCenterY * 0.5f;
                // speed = 0.5789f;

            } else if (i == 1) {
                angle = (float) ((30 + 270) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.1f;
                startY = (float) Math.sin(angle) * mCenterY * 0.2f;
                // speed = 0.7368f;

            } else if (i == 2) {
                angle = (float) ((40 + 270) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.25f;
                startY = (float) Math.sin(angle) * mCenterY * 0.4f;
                // speed = 0.5789f;

            } else if (i == 3) {
                angle = (float) ((60 + 270) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.3f;
                startY = (float) Math.sin(angle) * mCenterY * 0.33f;
                // speed = 0.5263f;

            } else if (i == 4) { // 星星变小
                angle = (float) ((50) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.6f;
                startY = (float) Math.sin(angle) * mCenterY * 0.7f;
                scale = 0.8f;
                // speed = 0.3157f; // 8

            } else if (i == 5) { // 星星变更小
                angle = (float) ((80) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.05f;
                startY = (float) Math.sin(angle) * mCenterY * 0.3f;
                scale = 0.6f;
                // speed = 0.4210f;

            } else if (i == 6) {
                angle = (float) ((145) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.5f;
                startY = (float) Math.sin(angle) * mCenterY * 0.28f;
                // speed = 0.5263f;

            } else if (i == 7) {
                angle = (float) ((205) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.5f;
                startY = (float) Math.sin(angle) * mCenterY * 0.15f;
                scale = 0.8f;
                // speed = 0.4210f;

            } else if (i == 8) {
                angle = (float) ((215) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.8f;
                startY = (float) Math.sin(angle) * mCenterY * 0.35f;
                // speed = 0.5789f;

            } else if (i == 9) {
                angle = (float) ((225) * Math.PI / 180);
                startX = (float) Math.cos(angle) * mCenterX * 0.4f;
                startY = (float) Math.sin(angle) * mCenterY * 0.5f;
                // speed = 0.5789f;
            }
            Matrix matrix = new Matrix();
            StarModel model = new StarModel(mStar, angle, startX, startY, matrix, scale, speed);

            mStarModelList.add(model);
        }
    }

}

第二:圆环动画


public class RingView extends View {

    private final static String	TAG			= "RingView";

    private int					mDuration	= 5000;

    private float				mCx;

    private float				mCy;

    private float				mMaxRadius;														// 最大半径

    private float				mOuterCurrentProgress;

    private float				mInnerCurrentProgress;

    private int[]				mColors;

    private PorterDuffXfermode mXfermode	= new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

    private Paint mPaint;															// 绘制外圆

    private Paint				mInnerPaint;

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

    public RingView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mColors = getContext().getResources().getIntArray(R.array.clor_ring);
        mPaint = new Paint();
        mPaint.setColor(mColors[0]);

        mInnerPaint = new Paint();
        mInnerPaint.setColor(Color.TRANSPARENT);
        mInnerPaint.setAlpha(0);
        mInnerPaint.setXfermode(mXfermode);
    }

    @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mCx = getMeasuredWidth() / 2;
        mCy = getMeasuredHeight() / 2;

        mMaxRadius = mCx;
    }

    @Override protected void onDraw(Canvas canvas) {
        int saveLayer = canvas.saveLayer(0, 0, mCx * 2, mCy * 2, mPaint, Canvas.ALL_SAVE_FLAG);

        canvas.drawCircle(mCx, mCx, mOuterCurrentProgress * mMaxRadius, mPaint);

        canvas.drawCircle(mCx, mCy, mInnerCurrentProgress * mMaxRadius, mInnerPaint);

        canvas.restoreToCount(saveLayer);
    }

    public void startAnim(int duration) {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override public void onAnimationUpdate(ValueAnimator animation) {
                mOuterCurrentProgress = (float) animation.getAnimatedValue();
                mPaint.setARGB(255, 255, (int) (229 - mOuterCurrentProgress * 68), 0);
                invalidate();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator()); // 先变快,然后减速

        ValueAnimator innerAnimator = ValueAnimator.ofFloat(0.01f, 1f);
        innerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override public void onAnimationUpdate(ValueAnimator animation) {
                mInnerCurrentProgress = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        innerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.setDuration(duration);
        animatorSet.playTogether(valueAnimator, innerAnimator);
        animatorSet.start();
    }

    private OnWillEndAnimatorListener onWillEndAnimatorListener;

    public void setOnWillEndAnimatorListener(OnWillEndAnimatorListener onWillEndAnimatorListener) {
        this.onWillEndAnimatorListener = onWillEndAnimatorListener;
    }

    public interface OnWillEndAnimatorListener {

        void onWillEndAnimatorListener(float value);
    }

}

第三结合小星星和圆环


public class StarLayout extends FrameLayout {

    private ImageView idIvBigStar;			// 大星星

    private RingView	idRingView;				// 圆环

    private StarView	idSmallStarListView;	// 所有的小星星

    public StarLayout(@NonNull Context context) {
        this(context, null);
    }

    public StarLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StarLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        inflate(context, R.layout.layout_star, this);

        idIvBigStar = findViewById(R.id.id_iv_big_star);
        idRingView = findViewById(R.id.id_ringview);
        idSmallStarListView = findViewById(R.id.id_starview);
    }

    public void startRingAnim(final int[] originLocation) {
        final int[] location = new int[2];
        idIvBigStar.post(new Runnable() {

            @Override public void run() {
                idIvBigStar.getLocationInWindow(location);

                final int disX = originLocation[0] - location[0];
                final int disY = originLocation[1] - location[1];

                idIvBigStar.setAlpha(0f);
                idRingView.startAnim(400);
                startBigStarScaleAnim(1200, 0).start();

                idSmallStarListView.startAnimation(10, 1600, 300);
                startBitStarTransAndScaleAnim(disX, disY, 1000, 1100);
            }
        });
    }

    private Animator startBigStarScaleAnim(int duration, int startDelay) {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 5f, 8f);

        valueAnimator.setInterpolator(new BounceInterpolator());
        valueAnimator.addListener(new AnimatorListenerAdapter() {

            @Override public void onAnimationStart(Animator animation) {
                idIvBigStar.setAlpha(1f);
            }
        });
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                idIvBigStar.setScaleX(value);
                idIvBigStar.setScaleY(value);
            }
        });
        valueAnimator.setDuration(duration);
        valueAnimator.setStartDelay(startDelay);
        return valueAnimator;
    }

    /***
     * 平移并且缩放动画
     */
    private void startBitStarTransAndScaleAnim(final int disX, final int disY, int duration, int delay) {
        ValueAnimator scaleAnim = ValueAnimator.ofFloat(8f, 1f);
        scaleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                idIvBigStar.setScaleX(value);
                idIvBigStar.setScaleY(value);
            }
        });

        ValueAnimator transAnim = ValueAnimator.ofFloat(0, 1f);
        transAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                idIvBigStar.setTranslationX(value * disX);
                idIvBigStar.setTranslationY(value * disY);
            }
        });

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(scaleAnim).with(transAnim);
        animatorSet.setDuration(duration);
        animatorSet.setStartDelay(delay);
        animatorSet.addListener(new AnimatorListenerAdapter() {

            @Override public void onAnimationEnd(Animator animation) { // 动画执行完毕
                if (onAnimationEnd != null) {
                    onAnimationEnd.onAnimationEnd();
                }
            }
        });
        animatorSet.start();
    }

    private OnAnimationEnd onAnimationEnd;

    public void setOnAnimationEnd(OnAnimationEnd onAnimationEnd) {
        this.onAnimationEnd = onAnimationEnd;
    }

    public interface OnAnimationEnd {

        void onAnimationEnd();
    }

}

源代码链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值