Android加载动画系列——BatteryLoading

Android加载动画系列——BatteryLoading

       小编在逛掘金社区的时候,一不小心看到了一篇讲加载动画的文章,于是点进去看了看,被这些炫酷的加载动画深深地吸引了,于是小编觉得有必要自己动手记录一下这些炫酷的脚在动画,顺便丰富一下自己的学习笔记。

       项目原地址:https://github.com/ldoublem/LoadingView

       让我们先来看看效果图:

             

       在此我就不做过多的分析,直接上源码。

1、BatteryLoading.java源码如下:

public class BatteryLoading extends View {
    private float mWidth = 0f;
    private float mHeight = 0f;

    private float mBatteryWidth;
    private float mBatteryHigh;
    private float mPadding = 0f;
    private float mBodyCorner = 0f;

    private float mBatterySpace = 0f;

    private Paint mPaint, mPaintHead, mPaintValue;


    private BatteryOrientation mBatteryOrientation = BatteryOrientation.HORIZONTAL;


    RectF rectFBody = null;
    RectF rectHead = null;

    public enum BatteryOrientation {
        VERTICAL, HORIZONTAL
    }

    private boolean mShowNum = false;


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

    public BatteryLoading(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BatteryLoading(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (getMeasuredWidth() > getHeight()) {
            mWidth = getMeasuredHeight();
            mHeight = getMeasuredHeight() * 0.8f;
        } else {
            mWidth = getMeasuredWidth();
            mHeight = getMeasuredWidth() * 0.8f;
        }
    }

    private void drawHead(Canvas canvas) {
        float mHeadWidth = mHeight / 6;
        rectHead = new RectF(
                mWidth - mPadding - mHeadWidth,
                mWidth / 2 - mHeadWidth / 2,
                mWidth - mPadding,
                mWidth / 2 + mHeadWidth / 2);
        canvas.drawArc(rectHead, -70, 140
                , false, mPaintHead);
    }


    private void drawBody(Canvas canvas) {
        float mHeadWidth = mHeight / 6;
        float x = (float) ((mHeadWidth / 2) * Math.cos(-70 * Math.PI / 180f));
        rectFBody = new RectF();
        rectFBody.top = mWidth / 2 - mHeight / 4 + mPadding;
        rectFBody.bottom = mWidth / 2 + mHeight / 4 - mPadding;
        rectFBody.left = mPadding;
        rectFBody.right = mWidth - mPadding - x - x - mBatterySpace;
        canvas.drawRoundRect(rectFBody, mBodyCorner, mBodyCorner, mPaint);
    }

    private void drawValue(Canvas canvas) {
        RectF rectFBatteryValueFill = new RectF();
        rectFBatteryValueFill.top = rectFBody.top + mBatterySpace;
        rectFBatteryValueFill.bottom = rectFBody.bottom - mBatterySpace;
        rectFBatteryValueFill.left = mPadding + mBatterySpace;
        rectFBatteryValueFill.right = rectFBody.right - mBatterySpace;

        RectF rectFBatteryValue = new RectF();
        rectFBatteryValue.top = rectFBatteryValueFill.top;
        rectFBatteryValue.bottom = rectFBatteryValueFill.bottom;
        rectFBatteryValue.left = rectFBatteryValueFill.left;
        rectFBatteryValue.right = rectFBatteryValueFill.right * mAnimatedValue;
        canvas.drawRoundRect(rectFBatteryValue, 1, 1, mPaintValue);
    }

    private void drawLogo(Canvas canvas) {

        mPaintHead.setTextSize(mHeight / 6);
        if (!mShowNum) {
            Path path = new Path();
            path.moveTo(mWidth / 2 - mHeight / 6, mWidth / 2 - dip2px(1.5f));
            path.lineTo(mWidth / 2 + dip2px(2f), mWidth / 2 + mHeight / 12);
            path.lineTo(mWidth / 2 + dip2px(1f), mWidth / 2);
            path.close();
            canvas.drawPath(path, mPaintHead);
            Path path2 = new Path();
            path2.moveTo(mWidth / 2 - dip2px(2f), mWidth / 2 - mHeight / 12);
            path2.lineTo(mWidth / 2 + mHeight / 6, mWidth / 2 + dip2px(1.5f));
            path2.lineTo(mWidth / 2 - dip2px(1f), mWidth / 2);
            path2.close();
            canvas.drawPath(path2, mPaintHead);
        } else {
            String text = String.valueOf((int) (mAnimatedValue * 100)) + "%";


            if (mBatteryOrientation == BatteryOrientation.VERTICAL) {
                Path p = new Path();
                p.moveTo(mWidth / 2, 0);
                p.lineTo(mWidth / 2, mWidth);
                canvas.drawTextOnPath(text, p,
                        mWidth / 2 - getFontLength(mPaintHead, text) / 2,
                        mWidth / 2 - mHeight / 2 - getFontHeight(mPaintHead, text) / 2,
                        mPaintHead);
            } else {
                canvas.drawText(text,
                        mWidth / 2 - getFontLength(mPaintHead, text) / 2,
                        mWidth / 2 + getFontHeight(mPaintHead, text) / 2,
                        mPaintHead);
            }

        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mBatteryOrientation == BatteryOrientation.VERTICAL)
            canvas.rotate(270, mWidth / 2, mWidth / 2);
        else
            canvas.rotate(0, mWidth / 2, mWidth / 2);
        canvas.save();

        drawHead(canvas);
        drawBody(canvas);
        drawValue(canvas);
        drawLogo(canvas);

        canvas.restore();

    }

    private void initPaint() {
        mBatteryHigh = dip2px(20);
        mPadding = dip2px(2);
        mBodyCorner = dip2px(1);
        mBatterySpace = dip2px(1);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.WHITE);
        mPaintHead = new Paint();
        mPaintHead.setAntiAlias(true);
        mPaintHead.setStyle(Paint.Style.FILL);
        mPaintHead.setColor(Color.WHITE);
        mPaintValue = new Paint();
        mPaintValue.setAntiAlias(true);
        mPaintValue.setStyle(Paint.Style.FILL);
        mPaintValue.setColor(Color.rgb(67, 213, 81));


    }

    public void startAnim() {
        stopAnim();
        startViewAnim(0f, 1f, 5000);
    }


    public void setValue(int value)//0-100
    {
        this.mAnimatedValue = value * 1.f / 100;
        invalidate();
    }

    public void setShowNum(boolean show) {
        this.mShowNum = show;
        invalidate();
    }

    public void setBatteryOrientation(BatteryOrientation batteryOrientation) {
        this.mBatteryOrientation = batteryOrientation;
        invalidate();
    }


    private ValueAnimator valueAnimator;
    private float mAnimatedValue = 0f;

    public void stopAnim() {
        if (valueAnimator != null) {
            clearAnimation();

            valueAnimator.setRepeatCount(0);
            valueAnimator.cancel();
            valueAnimator.end();
            mAnimatedValue = 0f;
            postInvalidate();
        }
    }


    private ValueAnimator startViewAnim(float startF, final float endF, long time) {
        valueAnimator = ValueAnimator.ofFloat(startF, endF);
        valueAnimator.setDuration(time);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);//无限循环
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {

                mAnimatedValue = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);

            }

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

            @Override
            public void onAnimationRepeat(Animator animation) {
                super.onAnimationRepeat(animation);
            }
        });
        if (!valueAnimator.isRunning()) {
            valueAnimator.start();

        }

        return valueAnimator;
    }

    public int dip2px(float dpValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public float getFontLength(Paint paint, String str) {
        Rect rect = new Rect();
        paint.getTextBounds(str, 0, str.length(), rect);
        return rect.width();
    }

    public float getFontHeight(Paint paint, String str) {
        Rect rect = new Rect();
        paint.getTextBounds(str, 0, str.length(), rect);
        return rect.height();

    }

}
为了考虑到电池的放置方式,提供了包含VERTICAL, HORIZONTAL两个方向的枚举变量。另外,为了切合时间,我们可以通过setShowNum(boolean)来设置是否显示百分比。

 

2、接下来就是如何使用的问题,首先我们需要在layout中引用自定义的动画控件,如下所示:

3、  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/darker_gray"
    android:gravity="center"
    android:orientation="vertical">

    <com.cyril.loadinganim.BatteryLoading
        android:id="@+id/battery"
        android:layout_width="65dp"
        android:layout_height="65dp" />

    <com.cyril.loadinganim.BatteryLoading
        android:id="@+id/battery2"
        android:layout_width="65dp"
        android:layout_height="65dp" />
</LinearLayout>

 

4、然后在相关的Activity中实现动画的播放和停止,使用事例如下:

batteryLoading = (BatteryLoading) findViewById(R.id.battery);
batteryLoading.setValue(50);
batteryLoading.setShowNum(true);
batteryLoading.setBatteryOrientation(BatteryLoading.BatteryOrientation.VERTICAL);
batteryLoading.startAnim();

batteryLoading1 = (BatteryLoading) findViewById(R.id.battery2);
batteryLoading1.setValue(50);
batteryLoading1.setShowNum(false);
batteryLoading1.setBatteryOrientation(BatteryLoading.BatteryOrientation.HORIZONTAL);
batteryLoading1.startAnim();
 

事例代码中,分别演示了,控件的水平放置和垂直放置,以及显示百分比和不显示百分比的情况。

5、  最后小编双手奉上源码的下载地址:http://download.csdn.net/detail/zhimingshangyan/9570386

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值