1. When customizing a ViewGroup, you usually only need to pay attention to onMeasure and onLayout. The complete code is as follows:

package com.example.view2 import android.content.Context import android.util.AttributeSet import android.util.Log import Android.view. view import Android.view. ViewGroup /** * Project name View2 * Creator * Created time 10/2/21 10:22am ** */ class MyFirstGroupView:ViewGroup{ val TAG = "MyFirstGroupView" var offset = 100 constructor(context: Context?) : super(context) {} constructor(context: Context? , attrs: AttributeSet?) : super(context, attrs) {} constructor(context: Context? , attrs: AttributeSet? , defStyleAttr: Int) : super( context, attrs, defStyleAttr ) {} override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, ChildCount = childCount () by on 10/2/21 10:31 AM childCount = childCount () for(i in (0.. childCount-1)){ val view:View = getChildAt(i) view? .let { val params = view.layoutParams val measureSpecWidthOfView = getChildMeasureSpec(widthMeasureSpec, 0, params.width) val measureSpecHeightOfView = getChildMeasureSpec( heightMeasureSpec, 0, params.height ) view.measure(measureSpecWidthOfView, // By on 10/2/21 10:50am Val widthMode = = // MeasureSpec.getMode(widthMeasureSpec) val widthSize = MeasureSpec.getSize(widthMeasureSpec) val heightMode = MeasureSpec.getMode(heightMeasureSpec) val heightSize = MeasureSpec.getSize(heightMeasureSpec) var width = 0 var height = 0 when(widthMode){ MeasureSpec.EXACTLY -> { width = widthSize } MeasureSpec.AT_MOST -> { for (i in 0.. childCount) { width = Math.max(height, getChildAt(i).measuredWidth + i * offset) } } MeasureSpec.UNSPECIFIED -> { width = widthSize } } when(heightMode){ MeasureSpec.EXACTLY -> { height = heightSize } MeasureSpec.AT_MOST -> { for (i in 0.. childCount) { height = height + getChildAt(i).measuredWidth } } MeasureSpec.UNSPECIFIED -> { height = heightSize } } // By on 10/2/21 10:55 AM setMeasuredDimension(width, height)} Override fun onLayout(changed: Boolean, l: Boolean) Int, t: Int, r: Int, b: Int) { val childCount = childCount var heightOffset = 0 for(i in 0.. childCount-1){ var view = getChildAt(i) view.layout( offset * i, heightOffset, view.measuredWidth + offset * i, view.measuredHeight + heightOffset ) heightOffset = heightOffset + view.measuredHeight } } }Copy the code

Measurement can be divided into 3 steps:

  • Measure the child View’s MeasureSpec against the parent container’s MeasureSpec and its own layout parameters.
  • The size of the parent container is determined by the parent’s MeasureSpec and the size of the child View.
  • Sets the size of the parent container

The layout is relatively simple, in fact, according to the preset rules, calculate the child View left, top, right and bottom, put it in the correct position

use

<? The XML version = "1.0" encoding = "utf-8"? > <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.example.view2.MyFirstGroupView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"> <TextView Android :layout_width="match_parent" Android :layout_height="wrap_content" Android :text=" I am the first line "></TextView> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher"/> <EditText Android :layout_width="wrap_content" Android :layout_height="wrap_content" Android: Hint =" This is a EditText"/> <Button Android :layout_width="match_parent" Android :layout_height="wrap_content" Android :text=" button"/> </com.example.view2.MyFirstGroupView> </androidx.constraintlayout.widget.ConstraintLayout>Copy the code

The running results are as follows: