How to create a custom View?

  1. The View is first inherited and then written to the layout
public class CircleLoadingView extends View { private Paint paint; public CircleLoadingView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); paint = new Paint(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int radius = DpPxUtils.dp2px(80); Canvas. Methods like drawCircle (0, 0, the radius, paint); }}Copy the code

2. Then write it to the layout

        <LinearLayout
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <com.smallcake.template.custom.CircleLoadingView
                android:background="@color/red"
                android:layout_width="100dp"
                android:layout_height="100dp"/>
        </LinearLayout>
Copy the code

3. Run and the effect comes out

Note:

1. Custom View constructor is a two-parameter constructor, do not write ratio error 2. Paint is best written by default because onDraw may be executed multiple times and the brush defaults to black

How to get the width and height of a custom View?

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
    }
Copy the code

Or: onDraw() via getWidth() and getHeight()

Note:

  • 1.onMeasureThe method is executed three times
  • 2. Understand firstMeasureSpecThere are three modes:UNSPECIFIED,AT_MOST,EXACTLY
  • 3.intType ofMeasureSpecTo represent the size of a component, this variable contains not only the size of the component, but also the size of the mode, a total of 32 bits, the first two bits to mark the mode, the last 30 bits to mark the space size
  • 4. In general, we often see this when we are customizing viewsAT_MOSTEXACTLY.UNSPECIFIEDThis pattern is applied to the system source code. Such asNestedScrollViewScrollView
  • 5. How to obtain the corresponding mode:int heightMode = MeasureSpec.getMode(heightMeasureSpec);

Reference: www.cnblogs.com/liushilin/p…

model describe The corresponding
Precision Mode 01 (MeasureSpec.EXACTLY) In this mode, the component is as long or wide as the value of size. The correspondingMATCH_PARENTTo determine the value of the.
Maximum Mode 11 (MeasureSpec.AT_MOST) So this is the parent component, the maximum amount of space that can be given, and the current component can only be as large or as wide as this, but it can also be smaller than this. The corresponding WRAP_CONETNT
Mode 00 not specified (MeasureSpec.UNSPECIFIED) This means that the current component can use whatever space it wants. all

Three. Some style Settings?

The effect code
anti-aliasing paint.setAntiAlias(true);
hollow paint.setStyle(Paint.Style.STROKE);
Line width paint.setStrokeWidth(8);

What is the difference between RectF and Rect?

  • 1. They are both used to construct a rectangular area
  • 2. The precision is different. Rect uses int as a value, RectF uses float as a value
  • 3. The methods provided by the two types are not identical. For example, RectF(Rect R) constructs a RectF object based on the given Rect object, thus extending the functions that Rect does not have

5. Draw circles

 canvas.drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
Copy the code

  • 1. Paint from the center of the brush. If the brush thickness is too wide, it will appear up, down, left and rightA less, we should set the radiusRadius - Brush group thick /2

Draw an arc

RectF rectF = new RectF(0, 0, width, height); Canvas. DrawArc (rectF, 0, 30, false, paint);Copy the code

DrawArc parameters :1. draw area, 2. start Angle, 3. end Angle, 4. Whether to connect center point, 5, brush

  • 1. If you want to draw an arc, not an arc section, set the brush style to hollow

paint.style = Paint.Style.STROKE

  • Demo: Draw an arc of loading progress, and combine animation, let it move
class CircleLoaindView : View { private val paint = Paint() private val paint2 = Paint() private var rectF: RectF? = null private var position = 0 private val paintWidth = 4f// Constructor (context: context? , attrs: AttributeSet?) : super(context, attrs) { paint.setColor(Color.parseColor("#DDDDDD")) paint.isAntiAlias = true paint.style = Paint.Style.STROKE paint.strokeWidth = paintWidth paint2.setColor(Color.parseColor("#535353")) paint2.isAntiAlias = true paint2.style = Paint.Style.STROKE paint2.strokeWidth = paintWidth paint2.strokeCap = Paint.Cap.ROUND } fun setPosition(position: Int) { this.position = position; invalidate() } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) val centerX = width / 2 val strokeWidth = centerX / radius canvas? .let {// draw the gray background circle canvas.drawcircle ((width / 2).tofloat (), (height / 2).tofloat (), (width / 2).toFloat() - paintWidth / 2, If (rectF == null) rectF = rectF ((strokeWidth / 2).tofloat () + paintWidth / 2, (strokeWidth / 2).toFloat() + paintWidth / 2, (2 * centerX - strokeWidth / 2).toFloat() - paintWidth / 2, (2 * Centerx-strokeWidth / 2).tofloat () -paintwidth / 2) // Draw the arc section canvas.drawarc (rectF!! , 3.6f * position, 360f / 30, false, paint2)}}}Copy the code
<com.smallcake.test.CircleLoaindView
        android:id="@+id/circleLoading"
        android:layout_width="200dp"
        android:layout_height="200dp"
        />
Copy the code
val animator: ObjectAnimator = ObjectAnimator.ofInt(circleLoading, "position", 0, 100)
        animator.duration = 1000
        animator.repeatCount = Animation.INFINITE
        animator.interpolator = LinearInterpolator()
        animator.start()

Copy the code