android custom View basic series one (imitation of the 365 calendar PC version loading animation)

Foreword:

Some time ago, the company's business was not busy, and I had nothing to do every day. I knew that there were many things to learn, but I didn't know where to start. I felt very uneasy, so I wanted to manage and plan my time. After careful selection, I fell in love with the 365 Calendar. I arranged my time every day and learned what to do in each time period. I started doing things in an orderly manner and felt much more fulfilled. It is recommended that friends also choose a suitable time management tool to manage and plan their time and fight. Sorry, I got off topic.

I refreshed my calendar today. Due to the network being temporarily unavailable, I saw the loading animation and planned to practice it. I attached a static picture to see the effect:


Just four small balls spinning and shaking in and out.

overview:

This article is all about the basic knowledge of drawing. It mainly involves the concept of a rotating canvas in drawing. You can learn about it yourself. The article will not introduce it in too much detail.

text:

First, analyze the attributes that need to be customized: the radius of the ball, the color values ​​of the four balls, and the distance of each ball from the central axis.

Let’s customize the properties first:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyViewAttrs">
        <!--小圆半径-->
        <attr name="radiu" format="integer"></attr>
        <!--四个圆的颜色-->
        <attr name="color_one" format="color"></attr>
        <attr name="color_two" format="color"></attr>
        <attr name="color_three" format="color"></attr>
        <attr name="color_four" format="color"></attr>
        <!--偏移中心点的距离-->
        <attr name="offset" format="integer"></attr>
    </declare-styleable>
</resources>


Customize a View and get the corresponding properties:

/*小圆半径*/
    private int radiu;

    /*四个球颜色值*/
    private int color_one;
    private int color_two;
    private int color_three;
    private int color_four;

    /*偏移中心轴距离*/
    private int offset;

    //绘图工具
    private Paint mPaint;

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

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

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

        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyViewAttrs,defStyleAttr,0);
        radiu = ta.getInt(R.styleable.MyViewAttrs_radiu,30);
        color_one = ta.getColor(R.styleable.MyViewAttrs_color_one, Color.BLACK);
        color_two = ta.getColor(R.styleable.MyViewAttrs_color_two, Color.BLACK);
        color_three = ta.getColor(R.styleable.MyViewAttrs_color_three, Color.BLACK);
        color_four = ta.getColor(R.styleable.MyViewAttrs_color_four, Color.BLACK);
        offset = ta.getInt(R.styleable.MyViewAttrs_offset,50);
        ta.recycle();

        mPaint = new Paint();
        mPaint.setStrokeWidth(3);
        mPaint.setAntiAlias(true);
    }


Then introduce the customized VIew into our layout file and set the corresponding attribute values:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/demo.bys.com.testmyview4"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <demo.bys.com.testmyview4.MyView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:radiu="60"
        custom:color_one="#FF7F00"
        custom:color_two="#FFFF00"
        custom:color_three="#63B8FF"
        custom:color_four="#0000EE"
        custom:offset="100"/>

</LinearLayout>

We also need to measure the width and height of the View in onMeasure to determine the location of the center point:

//View的宽高
private int mWidth,mHeight;
@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,400,getResources().getDisplayMetrics());
        }

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

        setMeasuredDimension(mWidth,mHeight);
    }


Okay, now our preparation work has been completed. We use the center point of the View as the central axis of the x and y axes. The four balls are offset by the same distance in the positive and negative directions on the x-axis and the y-axis. First we draw the static ball:

/*四个球*/
            mPaint.setColor(color_one);
            canvas.drawCircle(mWidth/2-offset,mHeight/2,radiu,mPaint);

            mPaint.setColor(color_two);
            canvas.drawCircle(mWidth/2+offset,mHeight/2,radiu,mPaint);

            mPaint.setColor(color_three);
            canvas.drawCircle(mWidth/2,mHeight/2-offset,radiu,mPaint);

            mPaint.setColor(color_four);
            canvas.drawCircle(mWidth/2,mHeight/2+offset,radiu,mPaint);
The effect is as shown in the figure:



Now we implement the dynamic effect of circle offset based on the static small circle, define the offset value, and offset judgment:

/*增还是减*/
    private boolean isChanging = false;

    /*变化的值*/
    private int offsetChange;

/*四个球*/
        mPaint.setColor(color_one);
        canvas.drawCircle(mWidth/2-offsetChange,mHeight/2,radiu,mPaint);

        mPaint.setColor(color_two);
        canvas.drawCircle(mWidth/2+offsetChange,mHeight/2,radiu,mPaint);

        mPaint.setColor(color_three);
        canvas.drawCircle(mWidth/2,mHeight/2-offsetChange,radiu,mPaint);

        mPaint.setColor(color_four);
        canvas.drawCircle(mWidth/2,mHeight/2+offsetChange,radiu,mPaint);


        if(isChanging){//递减
            if(offsetChange > offset){
                offsetChange --;
            }else{
                isChanging = false;
            }
        }else{//递加
            if(offsetChange < offset + 30){
                offsetChange ++;
            }else{
                isChanging = true;
            }
        }

        postInvalidateDelayed(30);
The offset change range is set to 30, judge increment or decrement, and replace the offset value of the ball with the changing offset value. At this point, the effect of the ball dynamically moving away/closer is achieved. If there is no dynamic picture, it will not be posted.

Next we are adding the effect of canvas rotation, setting a change ratio here:

/*旋转的比例值*/
    private int percent = 0;
Here we superimpose 2 degrees:
percent+=2;
canvas.rotate(percent,mWidth/2,mHeight/2);
Finally, the effect was achieved. In the Linux system, it is difficult to create dynamic renderings. I can only upload a static image. The source code will be attached later:

Attached is the complete code of View:

public class MyView extends View {

    /*小圆半径*/
    private int radiu;

    /*四个球颜色值*/
    private int color_one;
    private int color_two;
    private int color_three;
    private int color_four;

    /*偏移中心轴距离*/
    private int offset;

    //绘图工具
    private Paint mPaint;

    //View的宽高
    private int mWidth,mHeight;

    /*增还是减*/
    private boolean isChanging = false;

    /*变化的值*/
    private int offsetChange;

    /*旋转的比例值*/
    private int percent = 0;


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

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

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

        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyViewAttrs,defStyleAttr,0);
        radiu = ta.getInt(R.styleable.MyViewAttrs_radiu,30);
        color_one = ta.getColor(R.styleable.MyViewAttrs_color_one, Color.BLACK);
        color_two = ta.getColor(R.styleable.MyViewAttrs_color_two, Color.BLACK);
        color_three = ta.getColor(R.styleable.MyViewAttrs_color_three, Color.BLACK);
        color_four = ta.getColor(R.styleable.MyViewAttrs_color_four, Color.BLACK);
        offset = ta.getInt(R.styleable.MyViewAttrs_offset,50);
        ta.recycle();

        mPaint = new Paint();
        mPaint.setStrokeWidth(3);
        mPaint.setAntiAlias(true);
        offsetChange = offset;
    }

    @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,400,getResources().getDisplayMetrics());
        }

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

        setMeasuredDimension(mWidth,mHeight);
    }

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

        percent+=2;
        canvas.rotate(percent,mWidth/2,mHeight/2);

       /*四个球*/
        mPaint.setColor(color_one);
        canvas.drawCircle(mWidth/2-offsetChange,mHeight/2,radiu,mPaint);

        mPaint.setColor(color_two);
        canvas.drawCircle(mWidth/2+offsetChange,mHeight/2,radiu,mPaint);

        mPaint.setColor(color_three);
        canvas.drawCircle(mWidth/2,mHeight/2-offsetChange,radiu,mPaint);

        mPaint.setColor(color_four);
        canvas.drawCircle(mWidth/2,mHeight/2+offsetChange,radiu,mPaint);


        if(isChanging){//递减
            if(offsetChange > offset){
                offsetChange --;
            }else{
                isChanging = false;
            }
        }else{//递加
            if(offsetChange < offset + 30){
                offsetChange ++;
            }else{
                isChanging = true;
            }
        }


        postInvalidateDelayed(40);
    }


}




Source code:

csdn location: http://download.csdn.net/detail/liujibin1836591303/9723215



Guess you like

Origin blog.csdn.net/liujibin1836591303/article/details/53895027
Recommended