android custom View basic series one (imitation of 360 mobile guard mobile phone speed-up animation)

Foreword:

After using an Android phone for a long time, it will accumulate a lot of junk files/cache files, etc., which seriously affects the performance of the phone. It is key to always have a mobile phone management tool. I I have been using 360 Mobile Guard, and I think the acceleration ball is very effective. Today I will imitate and achieve a simple effect. First, I will upload two renderings:



























overview:

This article mainly focuses on realizing the animation effect of the circle in the middle. They are all very simple and basic effects. After reading a lot of blogs by Wing Master and Hy Master, I feel that no matter how complex the animation effect is, you must first learn to split it when you get it. Here we can split it into four main parts to achieve,

1. A semi-transparent circle, no need to move;

2. An arc with a blue color, the radius and the dots are the same as the first circle, and the arc will be drawn according to the proportion;

3. Display percentage text and percent sign inside the circle;

4. Prompt text inside the circle.

After splitting it, it is relatively simple for us to implement it. We first implement static effects and then dynamic effects.



text:

1. Basic preparations for drawing views:

Create a custom VIew and add it to the layout, customize attributes, and obtain attribute values ​​​​in the custom View. This part will not be explained too much, just go to the code. (Here we take the radius of the circle according to the width of the View, so we don’t define the attribute)

Attributes attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ClearViewAttrs">
        <!--底部圆的边线颜色-->
        <attr name="circleColor" format="color"></attr>
        <!--圆弧的颜色-->
        <attr name="arcColor" format="color"></attr>
        <!--提示性文字和百分比颜色-->
        <attr name="textColor" format="color"></attr>
        <!--百分比字体大小-->
        <attr name="percentTextSize" format="dimension"></attr>
        <!--%字体大小-->
        <attr name="markTextSize" format="dimension"></attr>
        <!--提示性文字字体大小-->
        <attr name="pointTextSize" format="dimension"></attr>
    </declare-styleable>
</resources>

It is very important to do a good job in animation decomposition and attribute analysis. You will understand it if you practice more.

Assign values ​​to properties in the layout file:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/demo.bys.com.clearviewdemo"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="demo.bys.com.clearviewdemo.MainActivity">

    <demo.bys.com.clearviewdemo.ClearView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        custom:circleColor="#cccccc"
        custom:arcColor="#5CACEE"
        custom:textColor="#5CACEE"
        custom:percentTextSize="40sp"
        custom:pointTextSize="14sp"
        custom:markTextSize="20sp"
        />


</RelativeLayout>

Get the corresponding attribute value in the custom VIew:

//圆的半径
    private int mRadius;
    //底部圆的边线颜色
    private int circleColor;
    //圆弧的颜色
    private int arcColor;
    //提示性文字和百分比颜色
    private int textColor;
    //百分比字体大小
    private int percentTextSize;
    //字体大小
    private int markTextSize;
    //提示性文字字体大小
    private int pointTextSize;

public ClearView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ClearViewAttrs,defStyleAttr,0);
        circleColor = ta.getColor(R.styleable.ClearViewAttrs_circleColor, Color.GRAY);
        arcColor = ta.getColor(R.styleable.ClearViewAttrs_arcColor,Color.BLUE);
        textColor = ta.getColor(R.styleable.ClearViewAttrs_textColor,Color.BLUE);
        percentTextSize = ta.getDimensionPixelSize(R.styleable.ClearViewAttrs_percentTextSize,20);
        markTextSize = ta.getDimensionPixelSize(R.styleable.ClearViewAttrs_markTextSize,10);
        pointTextSize = ta.getDimensionPixelSize(R.styleable.ClearViewAttrs_pointTextSize,15);
        ta.recycle();

    }

2. Measure the width and height of the View

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

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if(widthMode == MeasureSpec.EXACTLY){
            mWidth = widthSize;
        }else{
            mWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,200,getResources().getDisplayMetrics());
        }

        if(heightMode == MeasureSpec.EXACTLY){
            mHeight = heightSize;
        }else{
            mHeight = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,200,getResources().getDisplayMetrics());
        }

        //拿到半径的值,因为setStrokeWidth会有个边线的宽度,所以要减去宽度的一半
        mRadius = mWidth/2-10;
        setMeasuredDimension(mWidth,mHeight);

    }

3. Start drawing our animation by hand

Here we divide it into two major steps to achieve: static effects and dynamic effects.

a) Static effect drawing:

First, set the color and other attributes of the brush and draw the bottom circle:

//绘制底部的圆
        mPaint.setColor(circleColor);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(20);
        mPaint.setAntiAlias(true);

        canvas.drawCircle(mWidth/2,mHeight/2,mRadius,mPaint);
The effect is as shown in the figure:

To draw an arc with the same center and radius as a circle, first set a rectangle for the area where the arc is located:

private RectF mRectF;
//设置矩形区域
        mRectF.left = mWidth/2 - mRadius;
        mRectF.top = mHeight/2 - mRadius;
        mRectF.right = mWidth/2 + mRadius;
        mRectF.bottom = mHeight/2 + mRadius;
A word of caution, don't instantiate objects in the onDraw method.

The 3 o'clock direction is 0 degrees of the arc, increasing clockwise. We take the 12 o'clock direction (that is, -90 degrees) as the starting point. Here we first draw a static arc:

//绘制圆弧
        mPaint.setColor(arcColor);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(20);
        mPaint.setAntiAlias(true);

        canvas.drawArc(mRectF,-90,270,false,mPaint);
Starting from -90 degrees, draw an arc length of 270 degrees. The fourth parameter is set to false. If it is true, there will be a connection with the center of the circle.

Here we see the effect:

Next, start drawing the percentage, percent sign and prompt text. From the picture, we can see that the percentage text is displayed in the middle of the circle, the percent sign is in the lower right corner of the percentage value, and the prompt text is displayed in the empty space below the percentage text. middle part. Let’s first draw the percentage text in the middle part:

//百分比
    private String percentText = "75";
//绘制百分比文字
        mPaint.setColor(textColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(percentTextSize);
        mPaint.getTextBounds(percentText,0,percentText.length(),mRect);

        canvas.drawText(percentText,mWidth/2-mRect.width()/2,mHeight/2+mRect.height()/2,mPaint);
After setting the brush color and font size here, we need to get the width and height of the rectangular area Rect where the text is located, and obtain it through the mPaint.getTextBounds method. Then we set the starting point in the x direction to the leftmost side of the text rectangle and the starting point in the y direction. On the bottom side of the text rectangle.

The bottom side of the rectangular area where the percent sign is located is flush with the bottom side of the percentage value. The left side of the percent sign rectangle is offset a little from the right side of the percentage value. We set the brush and start drawing:

//绘制百分号
        mPaint.setColor(textColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(markTextSize);

        canvas.drawText("%",mWidth/2+mRect.width()/2+5,mHeight/2+mRect.height()/2,mPaint);
This must be drawn after the percentage value, because the width and height of the rectangular area where the percentage value is located are used.

Finally, draw the prompt text. The empty area where the percentage value is lowered is the drawing space. Draw it in the middle position, and also use the width and height values ​​of the rectangular area where the percentage value is located. Create a rectangular area Rect object with prompt text:

private Rect pointRect;
Set the brush and get the width and height of the rectangular area:
//提示文字
    private String pointText = "点我加速";

//绘制提示文字
        mPaint.setColor(textColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(pointTextSize);
        mPaint.getTextBounds(pointText,0,pointText.length(),pointRect);
Draw prompt text:
canvas.drawText(pointText,mWidth/2-pointRect.width()/2,((mRadius+mHeight/2)-(mHeight/2+mRect.height()/2))/2+mHeight/2+mRect.height()/2+pointRect.height()/2,mPaint);
This parameter is a bit long, so I’m not happy to split it. It’s mainly the third parameter. Find the value of the center point of the empty area below the percentage value in the Y direction, and add half the height of the rectangular area with the prompt text. The running effect is:


At this point, our static effect is complete.

b) To achieve animation effects:

Our animation effect here is: 1. After clicking View, the prompt text changes to "Loading", the arc gradually decreases to -90 degrees, and the percentage value gradually decreases to 0 at the same time; 2. The arc gradually increases, and the percentage value also decreases simultaneously. Increase.

Define a variable for the arc percentage, a variable for recording the last arc percentage, and a variable for recording the percentage that should be reached after clicking:

//弧度百分比
    private int ArcPercent = 0;

    //上一次弧度百分比
    private int lastPercent = 0;

    //当前获取到的百分比
    private int currentPercent = 0;

Get the value as a percentage:

percentText = ArcPercent + "";
The original hard-coded 270-degree arc drawing was changed to dynamic acquisition:
360*ArcPercent/100

A boolean to determine whether to perform animation:

//true是执行动画,false是静态
    private boolean isMoving = false;

A boolean that determines whether to add or subtract:

//false是递减到0,true是递增
    private boolean direction = false;

Add a click event to View:

implements View.OnClickListener
setOnClickListener(this);
@Override
    public void onClick(View view) {
        isMoving = true;
        pointText = "正在加速";
        invalidate();
    }
Finally, paste the code in onDraw:
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if(isMoving){
            if(!direction){
                if(ArcPercent > 0){
                    ArcPercent--;
                }else{
                    direction = true;
                }
            }else{
                pointText = "";
                currentPercent = random.nextInt(80);
                if(ArcPercent < currentPercent){
                    ArcPercent++;
                }else{
                    direction = false;
                    isMoving = false;
                    pointText="点击加载";
                }
            }
            percentText = ArcPercent + "";
            moveingView(canvas);
            postInvalidateDelayed(10);
        }else{
            percentText = ArcPercent + "";

            //绘制底部的圆
            mPaint.setColor(circleColor);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(20);
            mPaint.setAntiAlias(true);
            canvas.drawCircle(mWidth/2,mHeight/2,mRadius,mPaint);


            //绘制圆弧
            //计算弧度值
            mPaint.setColor(arcColor);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(20);
            mPaint.setAntiAlias(true);
            //设置矩形区域
            mRectF.left = mWidth/2 - mRadius;
            mRectF.top = mHeight/2 - mRadius;
            mRectF.right = mWidth/2 + mRadius;
            mRectF.bottom = mHeight/2 + mRadius;
            canvas.drawArc(mRectF,-90,360*ArcPercent/100,false,mPaint);

            //绘制百分比文字
            mPaint.setColor(textColor);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStrokeWidth(3);
            mPaint.setTextSize(percentTextSize);
            mPaint.getTextBounds(percentText,0,percentText.length(),mRect);
            canvas.drawText(percentText,mWidth/2-mRect.width()/2,mHeight/2+mRect.height()/2,mPaint);

            //绘制百分号
            mPaint.setColor(textColor);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStrokeWidth(3);
            mPaint.setTextSize(markTextSize);
            canvas.drawText("%",mWidth/2+mRect.width()/2+5,mHeight/2+mRect.height()/2,mPaint);


            //绘制提示文字
            mPaint.setColor(textColor);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStrokeWidth(3);
            mPaint.setTextSize(pointTextSize);
            mPaint.getTextBounds(pointText,0,pointText.length(),pointRect);
            canvas.drawText(pointText,mWidth/2-pointRect.width()/2,((mRadius+mHeight/2)-(mHeight/2+mRect.height()/2))/2+mHeight/2+mRect.height()/2+pointRect.height()/2,mPaint);
        }

    }

    /**
     * 动态效果绘制
     * @param canvas
     */
    private void moveingView(Canvas canvas){
        //绘制底部的圆
        mPaint.setColor(circleColor);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(20);
        mPaint.setAntiAlias(true);
        canvas.drawCircle(mWidth/2,mHeight/2,mRadius,mPaint);


        //绘制圆弧
        mPaint.setColor(arcColor);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(20);
        mPaint.setAntiAlias(true);
        //设置矩形区域
        mRectF.left = mWidth/2 - mRadius;
        mRectF.top = mHeight/2 - mRadius;
        mRectF.right = mWidth/2 + mRadius;
        mRectF.bottom = mHeight/2 + mRadius;
        canvas.drawArc(mRectF,-90,360*ArcPercent/100,false,mPaint);

        //绘制百分比文字
        mPaint.setColor(textColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(percentTextSize);
        mPaint.getTextBounds(percentText,0,percentText.length(),mRect);
        canvas.drawText(percentText,mWidth/2-mRect.width()/2,mHeight/2+mRect.height()/2,mPaint);

        //绘制百分号
        mPaint.setColor(textColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(markTextSize);
        canvas.drawText("%",mWidth/2+mRect.width()/2+5,mHeight/2+mRect.height()/2,mPaint);


        //绘制提示文字
        mPaint.setColor(textColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(pointTextSize);
        mPaint.getTextBounds(pointText,0,pointText.length(),pointRect);
        canvas.drawText(pointText,mWidth/2-pointRect.width()/2,((mRadius+mHeight/2)-(mHeight/2+mRect.height()/2))/2+mHeight/2+mRect.height()/2+pointRect.height()/2,mPaint);
    }

There is not much here, just the nesting of several judgments, as well as the start of View drawing, loop drawing, and end drawing. The random number I took directly from the last percentage here can be obtained by yourself. There are no dynamic renderings, so I can only post a few process diagrams:




Source site:http://download.csdn.net/detail/liujibin1836591303/9735822

Guess you like

Origin blog.csdn.net/liujibin1836591303/article/details/54375708