Customized View practice question arrangement

1. Dynamic audio playback bar chart

1. Rendering:

Insert image description here

2. Steps

(1) Create a new custom View class and inherit View
(2) Override the onDraw() method and use the brush and canvas to draw a certain number of columns in a loop

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

       //画柱形
       for (int i = 0; i < 10; i++){
           float mRandom = (float) Math.random();
           float currentHeight = mRectHeight*mRandom;
          canvas.drawRect((float) (mWidth*0.4/2+mRectWidth * i +offset),currentHeight, (float) (mWidth*0.4/2+mRectWidth*(i+1)),mRectHeight,mPaint1);
       }
       postInvalidateDelayed(800);
   }

(3) Rewrite the onSizeChange() method to achieve a columnar gradient effect

    @Override
   protected void onSizeChanged(int w, int h, int oldw, int oldh) {
       super.onSizeChanged(w, h, oldw, oldh);
       //实现音频柱的渐变效果
       mWidth = getWidth();
       mRectHeight = getHeight();
       mRectWidth = (int) (mWidth*0.6/10);
       mLinearGradient = new LinearGradient(
               0,0,mRectWidth,mRectHeight,Color.YELLOW,Color.BLUE, Shader.TileMode.CLAMP);
       mPaint1.setShader(mLinearGradient);
   }

(4) Just introduce it in the appropriate xml layout file

<com.example.test.MyView1
        android:id="@+id/myView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

Attachment: All codes are as follows:

package com.example.test;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.Nullable;

public class MyView1 extends View {

   Paint mPaint1;  //画笔
   int mWidth = 200;
   int mHeight = 1000;
   int mRectWidth = 30; //柱形的宽度
   int mRectHeight = 200; //柱形的高度
   int offset = 5; //柱形之间的距离

   LinearGradient mLinearGradient;

   public MyView1(Context context) {
       super(context);
       init();
   }

   public MyView1(Context context, @Nullable AttributeSet attrs) {
       super(context, attrs);
       init();
   }

   public MyView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
       super(context, attrs, defStyleAttr);
       init();
   }

   private void init(){
   	   //初始化画笔和画笔的颜色、样式等
       mPaint1 = new Paint();
       mPaint1.setColor(getResources().getColor(R.color.purple_200));
   }

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

       //画柱形
       for (int i = 0; i < 10; i++){
           float mRandom = (float) Math.random();
           float currentHeight = mRectHeight*mRandom;
          canvas.drawRect((float) (mWidth*0.4/2+mRectWidth * i +offset),currentHeight, (float) (mWidth*0.4/2+mRectWidth*(i+1)),mRectHeight,mPaint1);
       }
       postInvalidateDelayed(800);
   }

   @Override
   protected void onSizeChanged(int w, int h, int oldw, int oldh) {
       super.onSizeChanged(w, h, oldw, oldh);
       //实现音频柱的渐变效果
       mWidth = getWidth();
       mRectHeight = getHeight();
       mRectWidth = (int) (mWidth*0.6/10);
       mLinearGradient = new LinearGradient(
               0,0,mRectWidth,mRectHeight,Color.YELLOW,Color.BLUE, Shader.TileMode.CLAMP);
       mPaint1.setShader(mLinearGradient);
   }
}

2. Custom size circles

1. Effect drawing

a circle

2. Steps

(1) Create a new custom View class and inherit View
(2) Custom properties can be set

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //自定义属性
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.MyView);
        mColor = a.getColor(R.styleable.MyView_circle_color,Color.RED);
        a.recycle();
        init();
    }

Create attrs.xml under the values ​​file, you can set the color, and you can set it to the brush later.

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //自定义属性
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.MyView);
        mColor = a.getColor(R.styleable.MyView_circle_color,Color.RED);
        a.recycle();
        init();
    }

(3) Rewrite onMeasure() and customize the drawing size

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //宽测量模式
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        //宽测量大小
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        //高测量模式
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        //高测量大小
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(200,200);
        }else if (widthSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(200,heightSpecSize);
        }else if (heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(widthSpecSize,200);
        }else{
            setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
        }
    }

(4) Rewrite the onDraw() method to draw a circle

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth()-getPaddingLeft()-getPaddingLeft();
        int height = getHeight()-getPaddingLeft()-getPaddingLeft();
        int radius = Math.min(width,height)/2;
        canvas.drawCircle((float) width/2+getPaddingLeft(),(float) height/2+getPaddingLeft(),radius,paint);
    }

(5) When calling the corresponding place, you need to pay attention to setting wrap_content, because if you want to achieve the effect of overriding the onDraw method, you need to support wrap_content yourself, and padding also needs to be handled by yourself.

<com.example.test.MyView
        android:id="@+id/myView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        app:layout_constraintTop_toBottomOf="@+id/text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

Attached: All codes

package com.example.test;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;

public class MyView extends View {

    public int mColor = Color.RED;
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    public MyView(Context context) {
        super(context);
        init();
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
         init();
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //自定义属性
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.MyView);
        mColor = a.getColor(R.styleable.MyView_circle_color,Color.RED);
        a.recycle();
        init();
    }

    //初始化画笔
    private void init(){
        paint.setColor(mColor);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //宽测量模式
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        //宽测量大小
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        //高测量模式
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        //高测量大小
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(200,200);
        }else if (widthSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(200,heightSpecSize);
        }else if (heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(widthSpecSize,200);
        }else{
            setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth()-getPaddingLeft()-getPaddingLeft();
        int height = getHeight()-getPaddingLeft()-getPaddingLeft();
        int radius = Math.min(width,height)/2;
        canvas.drawCircle((float) width/2+getPaddingLeft(),(float) height/2+getPaddingLeft(),radius,paint);
    }

}

Guess you like

Origin blog.csdn.net/qq_46269365/article/details/129198883