Today, I found that there are still some people who can not customize the view combination, so I wrote this simple example, hoping to help the students who are new to Android

Four steps

Edit the XML file that you need to combine the views

Let’s say I want to write a generic page header, like this

<? The XML version = "1.0" encoding = "utf-8"? > <merge xmlns:android="http://schemas.android.com/apk/res/android"> <! -- Set the height and padding of the left and right text to get a larger click area. <ImageView android:id="@+id/iv_back" Android :layout_width="50dp" Android :layout_height=" 50DP" android:padding="14dp" android:src="@drawable/ic_back"/> <TextView android:id="@+id/tv_title" android:layout_width="0dp" Android :layout_height="50dp" Android :layout_weight="1" Android :text=" title "Android :textColor="@color/white" android:textSize="18sp" android:textStyle="bold" android:gravity="center"/> <TextView android:id="@+id/tv_operation" Android :layout_width=" 50DP "Android :layout_height=" 50DP" Android :text=" filter "Android :textSize="16sp" android:textColor="@color/white" android:textStyle="bold" android:gravity="center"/> </merge>Copy the code

The root layout is merge, not the usual LinearLayout or other ViewGroup, because your custom combined view is a ViewGroup. In XML, the root layout can be reduced or reduced. As for the attributes you need to set in the root layout, such as horizontal and vertical or center of gravity, you can set them in your custom View, see below

2, New you need to combine the view rewrite constructor

class CustomViewGroup: LinearLayout { constructor(context: Context): // Notice that this() calls the second constructor(context: context, attrs: AttributeSet?). : this(context, attrs, 0)// Notice that this() calls the third constructor(context: context, attrs: AttributeSet? , defStyleAttr: Int): super(context, attrs, defStyleAttr) {} }Copy the code

Edit the custom properties of the composite view that you need

Find attrs. XML in the res/values folder. If not attrs. XML, right-click values -> new -> values Resource File and name attrs. Add declare-styleable to the attrs. XML file

<? The XML version = "1.0" encoding = "utf-8"? > <resources> // The name of the CustomViewGroup is the same as the name of the view created in step 2. <declare-styleable name="CustomViewGroup"> <attr name="title" format="string"/> <attr name="operation"  format="string"/> </declare-styleable> </resources>Copy the code

Start writing your code in your custom composite View

class CustomViewGroup: LinearLayout { lateinit var title: TextView lateinit var operation: TextView constructor(context: Context): this(context, null) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet? , defStyleAttr: Int): Super (context, attrs, defStyleAttr) {// Since we introduced the merge layout file root layout, and our CustomViewGroup inherits the LinearLayout, So we set a couple of properties here: this.orientation = HORIZONTAL this.gravity = gravity.CENTER_VERTICAL this.setBackgroundColor(ContextCompat.getColor(context, R.color.colorAccent)) init(context, attrs) } private fun init(context: Context, attrs: AttributeSet?) {// Load your composite layout file into this custom CustomViewGroup val inflate = layoutinflater.from (context).inflate(r.layout.view_custom_viewgroup, This) // Use findViewById to find the control in your layout file val ivBack: ImageView = constructor.findViewById (r.d.iv_back) If you have any other operation can be custom ivBack. Other operating method setOnClickListener {(context as the Activity). Finish ()} title = inflate. The findViewById (R.i which v_title) Operation = constructor.findViewById (R.i.D.t.v_operation) // Retrieves configurable properties, Set up to control val attr = context. ObtainStyledAttributes (attrs. R.styleable.CustomViewGroup) title.text = attr.getString(R.styleable.CustomViewGroup_title) operation.text = Attr. Get string (R.s tyleable. CustomViewGroup_operation) / / run out to recycle attr. Recycle ()} / * can provide set text method * / fun setTitle (s: String){ title.text = s } fun setOperation(s: String)} {operation. The text = s / / set to right click to monitor fun text setOnOperationClickListener (listener: OnOperationClickListener){ operation.setOnClickListener { listener.onClick() } } } interface OnOperationClickListener{ fun onClick() }Copy the code

use

In the XML

<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical"> <! -- you -- -- > < com. Limeng. Thecreator. The CustomViewGroup android: id = "@ + id/cvg_title" android: layout_width = "match_parent" Android :layout_height="wrap_content" APP :operation=" filter "/> <Button android:id="@+id/bt_change_title" Android :layout_width="wrap_content" Android :layout_height="wrap_content" Android :text=" change the title "/> <Button id: 0 android:id="@+id/bt_change_operation" android:layout_width="wrap_content" android:layout_height="wrap_content" Android :text=" change the right text "/> </LinearLayout>Copy the code

In the activity

/ / is cvg_title CustomViewGroup / / call the click event cvg_title setOnOperationClickListener (object: OnOperationClickListener{override fun onClick() {val makeText = makeText(this@CustomViewGroupActivity, "Don't hit me ", Toast.length_short) maketext.setgravity (Gravity.TOP,0,0) maketext.show ()}}) // call setTitle Bt_change_title. SetOnClickListener {cvg_title. SetTitle (" I go ")} / / call setOperation bt_change_operation. SetOnClickListener {cvg_title.setOperation(" You go ")}Copy the code

The end of the

Git address: gitee.com/woslxm_lime…