Android酷炫加载进度动画

概述

本自定义动画进度酷炫View,是加载进度动画的自定义View,继承于ImageView来实现,主要实现蒙层加载进度的加载进度效果。 支持水平左右加载和垂直上下加载四个方向,同时也支持自定义蒙层进度颜色。

详细

一、概述

本自定义动画进度酷炫View,是加载进度动画的自定义View,继承于ImageView来实现,主要实现蒙层加载进度的加载进度效果。

支持水平左右加载和垂直上下加载四个方向,同时也支持自定义蒙层进度颜色。

直接看下面的效果图吧。

二、效果图

废话不说,先来看看效果图吧~~

三、实现原理方案

1、自定义View-XCLoadingImageView,继承ImageVIew来实现,这样就不用自己再处理drawable和测量的工作内容。

2、根据蒙层颜色创建一个蒙层bitmap,然后根据这个bitmap来创建一个ClipDrawable,最后利用ClipDrawable的level属性

来裁剪显示区域进度,从而达到加载进度的效果。

3、最后利用属性动画技术或ClipDrawable的setLevel()方法来达到进度的效果。

 

四、自定义加载进度效果XCLoadingImageView的具体实现

1、初始化需要用到的数据变量以及画笔以及属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private Paint mImagePaint;    private int mImageHeight, mImageWidth;    private boolean mIsAutoStart = false;    private int mMaskColor = Color.TRANSPARENT;    private ClipDrawable mClipDrawable;    private Drawable mMaskDrawable;    private int maskHeight;    private int mProgress;    private ObjectAnimator mAnimator;    private long mAnimDuration = 2500;    private float mScaleX, mScaleY;    private int mGravity = Gravity.BOTTOM;    private int mOrientaion = ClipDrawable.VERTICAL;    private int mMaskOrientation = MaskOrientation.BottomToTop;    //Loading oriention
    public static final class MaskOrientation {        public static final int LeftToRight = 1;        public static final int RightToLeft = 2;        public static final int TopToBottom = 3;        public static final int BottomToTop = 4;
    }/**
     * initial attributes     */
    private void initAttrs(Context context, AttributeSet attrs) {        if (attrs == null) {            return;
        }
        TypedArray t = context.obtainStyledAttributes(attrs, R.styleable.XCLoadingImageView);
        mMaskColor = t.getColor(R.styleable.XCLoadingImageView_mask_color, mMaskColor);
        mIsAutoStart = t.getBoolean(R.styleable.XCLoadingImageView_auto_start_anim, mIsAutoStart);
        setMaskColor(mMaskColor);
        t.recycle();
    }    /**
     * initial paint     */
    private void init() {        if (mImagePaint == null) {
            mImagePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mImagePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        }
    }

 

2、初始化蒙层Bitmap以及创建加载进度用的ClipDrawable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void initMaskBitmap(int maskColor) {
    Drawable drawable = getDrawable();
    if (drawable == null) {
        return;
    }
    Bitmap bgBmp = ((BitmapDrawable) drawable).getBitmap();
    mImageWidth = drawable.getIntrinsicWidth();
    mImageHeight = drawable.getIntrinsicHeight();
 
    Bitmap fgBmp = Bitmap.createBitmap(mImageWidth, mImageHeight, Bitmap.Config.ARGB_8888);
    Canvas fgCanvas = new Canvas(fgBmp);
    fgCanvas.drawColor(maskColor);
 
    Bitmap bitmap = combineBitmap(bgBmp, fgBmp);
    mMaskDrawable = new BitmapDrawable(null, bitmap);
    mClipDrawable = new ClipDrawable(mMaskDrawable, mGravity, mOrientaion);
}

3、合并蒙层Bitmap和ImageView的src的drawable为新的Bitmap

1
2
3
4
5
6
7
8
9
10
/**
 * combine tow bitmap to one bitmap
 */
private Bitmap combineBitmap(Bitmap bg, Bitmap fg) {
    Bitmap bmp = Bitmap.createBitmap(mImageWidth, mImageHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bmp);
    canvas.drawBitmap(bg, 0, 0, null);
    canvas.drawBitmap(fg, 0, 0, mImagePaint);
    return bmp;
}

4、重写ImageVIew的onDraw()方法来把创建的ClipDrawable绘制到Canvas上

1
2
3
4
5
6
7
8
9
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.save();
    canvas.scale(mScaleX, mScaleY);
    mClipDrawable.setBounds(getDrawable().getBounds());
    mClipDrawable.draw(canvas);
    canvas.restore();
}

 

5、弹通过属性动画或者setLevel,并调用postInvalidate()来重绘,从而达到进度刷新的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void initAnim() {
    stopAnim();
    mAnimator = ObjectAnimator.ofInt(mClipDrawable, "level", 0, 10000);
    mAnimator.setDuration(mAnimDuration);
    mAnimator.setRepeatCount(ValueAnimator.INFINITE);
    mAnimator.setRepeatMode(ValueAnimator.RESTART);
    mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            postInvalidate();
        }
    });
    if (mIsAutoStart) {
        mAnimator.start();
    }
}
public void setProgress(int progress){
    mProgress = progress;
    mClipDrawable.setLevel(mProgress * 100);
    postInvalidate();
}

 

五、如何使用该自定义LoadingView控件

1、使用该自定义LoadingView非常简单,和使用普通ImageView差不对哦,只需设置下方向和蒙层颜色即可

1
2
3
4
5
6
7
8
9
10
11
12
public class MainActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        XCLoadingImageView imageView2 = (XCLoadingImageView) findViewById(R.id.img2);
        imageView2.setMaskOrientation(XCLoadingImageView.MaskOrientation.LeftToRight);
        imageView2.setProgress(50);
    }
}

 

六、项目结构目录截图

aaa.png

 

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

posted on   demo例子集  阅读(6365)  评论(0编辑  收藏  举报

(评论功能已被禁用)
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示