升级动画(图标颜色慢慢填充效果)

自定义动画,控制波纹方向:

public class WaveLoadingDrawable extends Drawable implements Animatable {

    private static final float WAVE_AMPLITUDE_FACTOR = 0.15f;
    private static final float WAVE_SPEED_FACTOR = 0.02f;
    private Drawable mDrawable;
    private int mWidth, mHeight;
    private int mWaveAmplitude, mWaveLength, mWaveOffset, mWaveStep, mWaveLevel;
    private ValueAnimator mAnimator;
    private float mProgress = 0.3f;
    private Paint mPaint;
    private Bitmap mMask;
    private Matrix mMatrix = new Matrix();
    private boolean mRunning = false;
    private boolean mIndeterminate = false;

    private PorterDuffXfermode sXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    private static ColorFilter sGrayFilter = new ColorMatrixColorFilter(new float[]{//变灰
            0.264F, 0.472F, 0.088F, 0, 0,
            0.264F, 0.472F, 0.088F, 0, 0,
            0.264F, 0.472F, 0.088F, 0, 0,
            0,      0,      0,      0.5F, 0
    });

    private int direction;//0:上涨;1:左涨;2:右涨

//    private static ColorFilter sGrayFilter = new ColorMatrixColorFilter(new float[]{//变白
//            1.5F, 1.5F, 1.5F, 0, -1,
//            1.5F, 1.5F, 1.5F, 0, -1,
//            1.5F, 1.5F, 1.5F, 0, -1,
//            0,    0,    0,    1, 0
//
//    });

    private ColorFilter mCurFilter = null;

    private Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long l) {
            invalidateSelf();
            if (mRunning) {
                Choreographer.getInstance().postFrameCallback(this);
            }
        }
    };

    public WaveLoadingDrawable(Drawable drawable,int direction) {
        init(drawable,direction);
    }

    public WaveLoadingDrawable(Context context, int imgRes,int direction) {
        Drawable drawable;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            drawable = context.getDrawable(imgRes);
        } else {
            drawable = context.getResources().getDrawable(imgRes);
        }
        init(drawable,direction);
    }

    private void init(Drawable drawable,int direction) {
        this.direction = direction;
        mDrawable = drawable;
        mWidth = mDrawable.getIntrinsicWidth();
        mHeight = mDrawable.getIntrinsicHeight();
        if(direction == 0) {
            mWaveAmplitude = Math.max(8, (int) (mHeight * WAVE_AMPLITUDE_FACTOR));
            mWaveLength = mWidth;
            mWaveStep = Math.max(1, (int) (mWidth * WAVE_SPEED_FACTOR));

            mMatrix.reset();
            mMask = createHorizontalMask(mWidth, mWaveLength, mWaveAmplitude);
        }else{
            mWaveAmplitude = Math.max(8, (int) (mWidth * WAVE_AMPLITUDE_FACTOR));
            mWaveLength = mHeight;
            mWaveStep = Math.max(1, (int) (mHeight* WAVE_SPEED_FACTOR));

            mMatrix.reset();
            mMask = createVerticalMask(mHeight, mWaveLength, mWaveAmplitude);
            if(direction == 1){
                sXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
            }
        }
        mPaint = new Paint();
        mPaint.setFilterBitmap(false);
        mPaint.setColor(Color.BLACK);
        mPaint.setXfermode(sXfermode);

        mAnimator = ValueAnimator.ofFloat(0, 1);
        mAnimator.setInterpolator(new DecelerateInterpolator());
        mAnimator.setRepeatMode(ValueAnimator.RESTART);
        mAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mAnimator.setDuration(5000);
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                setProgress((float) valueAnimator.getAnimatedValue());
                if (!mRunning) {
                    invalidateSelf();
                }
            }
        });

        setProgress(0);
        start();
    }

    /**
     * Set wave move distance (in pixels) in very animation frame
     * @param step distance in pixels
     */
    public void setWaveSpeed(int step) {
        if(direction ==0) {
            mWaveStep = Math.min(step, mWidth / 2);
        }else{
            mWaveStep = Math.min(step, mHeight / 2);
        }
    }

    /**
     * Set wave amplitude (in pixels)
     * @param amplitude
     */
    public void setWaveAmplitude(int amplitude) {
        if(direction ==0) {
            amplitude = Math.max(0, Math.min(amplitude, mHeight / 2));
            if (mWaveAmplitude != amplitude) {
                mWaveAmplitude = amplitude;
                mMask = createHorizontalMask(mWidth, mWaveLength, mWaveAmplitude);
                invalidateSelf();
            }
        }else{
            amplitude = Math.max(0, Math.min(amplitude, mWidth / 2));
            if (mWaveAmplitude != amplitude) {
                mWaveAmplitude = amplitude;
                mMask = createVerticalMask(mHeight, mWaveLength, mWaveAmplitude);
                invalidateSelf();
            }
        }
    }

    /**
     * Set wave length (in pixels)
     * @param length
     */
    public void setWaveLength(int length) {
        if(direction ==0) {
            length = Math.max(8, Math.min(mWidth * 2, length));
            if (length != mWaveLength) {
                mWaveLength = length;
                mMask = createHorizontalMask(mWidth, mWaveLength, mWaveAmplitude);
                invalidateSelf();
            }
        }else{
            length = Math.max(8, Math.min(mHeight * 2, length));
            if (length != mWaveLength) {
                mWaveLength = length;
                mMask = createVerticalMask(mHeight, mWaveLength, mWaveAmplitude);
                invalidateSelf();
            }
        }
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        mDrawable.setBounds(left, top, right, bottom);
    }

    @Override
    public int getIntrinsicHeight() {
        return mHeight;
    }

    @Override
    public int getIntrinsicWidth() {
        return mWidth;
    }

    @Override
    public void draw(Canvas canvas) {
        mDrawable.setColorFilter(sGrayFilter);
        mDrawable.draw(canvas);
        mDrawable.setColorFilter(mCurFilter);

        if (mProgress <= 0.001f) {
            return;
        }

        int sc = canvas.saveLayer(0, 0, mWidth, mHeight, null,Canvas.ALL_SAVE_FLAG);

        mDrawable.draw(canvas);

        if (mProgress >= 0.999f) {
            return;
        }

        mWaveOffset += mWaveStep;
        if (mWaveOffset > mWaveLength) {
            mWaveOffset -= mWaveLength;
        }
        switch(direction){
            case 0:
                if (mWaveLevel > 0) {
                    mPaint.setColor(Color.TRANSPARENT);
                    canvas.drawRect(0, 0, mWidth, mWaveLevel, mPaint);
                    mPaint.setColor(Color.WHITE);
                }
                mMatrix.setTranslate(-mWaveOffset, mWaveLevel);
                canvas.drawBitmap(mMask, mMatrix, mPaint);
            break;
            case 1:
                if (mWaveLevel > 0) {
                    mPaint.setColor(Color.TRANSPARENT);
                    canvas.drawRect(mWaveLevel,0,mWidth,mHeight,mPaint);
                    mPaint.setColor(Color.WHITE);

                }
                mMatrix.setTranslate(mWaveLevel-2*mWaveAmplitude,-mWaveOffset);
                canvas.drawBitmap(mMask, mMatrix, mPaint);
                mPaint.setColor(Color.WHITE);
                canvas.drawRect(mWaveLevel,0,mWidth,mHeight,mPaint);
                break;
            case 2:
                if (mWaveLevel > 0) {
                    mPaint.setColor(Color.TRANSPARENT);
                    canvas.drawRect(0,0,mWaveLevel,mHeight,mPaint);
                    mPaint.setColor(Color.WHITE);
                }
                mMatrix.setTranslate(mWaveLevel,-mWaveOffset);
                canvas.drawBitmap(mMask, mMatrix, mPaint);
                break;
            default:
            break;
        }

        canvas.restoreToCount(sc);
    }

    @Override
    protected boolean onLevelChange(int level) {
        setProgress(level/100f);
        return true;
    }

    @Override
    public void setAlpha(int i) {
        mDrawable.setAlpha(i);
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mCurFilter = colorFilter;
        invalidateSelf();
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public void start() {
        mRunning = true;
        Choreographer.getInstance().postFrameCallback(mFrameCallback);
    }

    @Override
    public void stop() {
        mRunning = false;
        Choreographer.getInstance().removeFrameCallback(mFrameCallback);
    }

    @Override
    public boolean isRunning() {
        return mRunning;
    }

    /**
     * 开启自动播放
     * @param indeterminate
     */
    public void setIndeterminate(boolean indeterminate) {
        mIndeterminate = indeterminate;
        if (mIndeterminate) {
            mAnimator.start();
        } else {
            mAnimator.cancel();
        }
    }

    private void setProgress(float progress) {
        mProgress = progress;
        if(direction ==0) {
            mWaveLevel = mHeight - (int) ((mHeight + mWaveAmplitude * 2) * mProgress);
        }else if (direction == 1){
            mWaveLevel = (int)((mWidth + mWaveAmplitude * 2) * mProgress);
        }else if (direction == 2){
            mWaveLevel = mWidth - (int) ((mWidth + mWaveAmplitude * 2) * mProgress);
        }
        invalidateSelf();
    }

    /**
     * 创建水平方向的波浪
     * @param width
     * @param length
     * @param amplitude
     * @return
     */
    private static Bitmap createHorizontalMask(int width, int length, int amplitude) {

        final int count = (int) Math.ceil((width + length) / (float)length);

        Bitmap bm = Bitmap.createBitmap(length * count, amplitude * 2, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        Path path = new Path();
        path.moveTo(amplitude,0);
        final float stepX = length / 4f;
        float x = 0;
        float y = 0;
        for (int i = 0; i < count * 2; i++) {
            x += stepX;
            path.quadTo(x, y, x+stepX, amplitude);
            x += stepX;
            y = bm.getHeight() - y;
        }
        path.lineTo(bm.getWidth(), bm.getHeight());
        path.lineTo(0, bm.getHeight());
        path.close();

        c.drawPath(path, p);
        return bm;
    }

    /**
     * 创建垂直方向的波浪
     * @param height
     * @param length
     * @param amplitude
     * @return
     */
    private static Bitmap createVerticalMask(int height, int length, int amplitude) {

        final int count = (int) Math.ceil((height + length) / (float)length);

        Bitmap bm = Bitmap.createBitmap(amplitude * 2,length * count,  Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        Path path = new Path();
        path.moveTo(amplitude, 0);
        final float stepX = length / 4f;
        float x = 0;
        float y = 0;
        for (int i = 0; i < count * 2; i++) {
            y += stepX;
            path.quadTo(x, y, amplitude, y+stepX);
            y += stepX;
            x = bm.getWidth() - x;
        }
        path.lineTo(bm.getWidth(), bm.getHeight());
        path.lineTo(bm.getWidth(), 0);
        path.close();

        c.drawPath(path, p);
        return bm;
    }
}

调用方式:

WaveLoadingDrawable loadingDrawable = new WaveLoadingDrawable(mActivity, R.mipmap.ic_upgrade_red,0);
loadingDrawable.setWaveAmplitude(1);
upgradeImageView.setImageDrawable(upgradeDrawable);

下载进度(1-100):loadingDrawable.setLevel(“当前进度”);

                              

参考https://github.com/race604/WaveLoading

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值