Combined controls in custom controls

Combination control of custom control

Writing Android code has always used its own controls, and sometimes some parts are reused, which is troublesome to change. It would not be very cool to assemble this part to form a separate control. So, you can use the composite control.

For example: a search box with some buttons, toolbar, etc.

In fact, there are two types of custom controls:

  • One is this combination control, which assembles the original control into a commonly used control;

  • The other is a control that is completely drawn by yourself, which cannot be implemented using the built-in controls.

1. Pull out reused layouts

Write a separate xml file for your reuse of a set of controls

For example: a picture and a text form a combination control

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
      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">    

<ImageView        
	android:id="@+id/image"        
	android:layout_width="wrap_content"        
	android:layout_height="wrap_content"           	
	app:layout_constraintTop_toTopOf="parent"        
	app:layout_constraintLeft_toLeftOf="parent"/>    
	
<TextView        
	android:id="@+id/text"        
	android:layout_width="wrap_content"        
	android:layout_height="wrap_content"        
	android:layout_marginTop="2dp"        						
	app:layout_constraintTop_toBottomOf="@+id/image"        	
	app:layout_constraintLeft_toLeftOf="@+id/image"     
	app:layout_constraintRight_toRightOf="@+id/image"/>

</androidx.constraintlayout.widget.ConstraintLayout>

In this way, you don't have to write a thing repeatedly in a layout file. However, you can also use merge, so that there is no more layout. It is currently in a constraintlayout layout, and customization is also a constraintlayout. In the customization, and insert the layout of the xml file, there is one more layer. If you use merge, there is one less layer. Accordingly, efficiency should be improved.

2. Bind the extracted layout to the custom view
  • First customize a view that inherits from constraintlayout

  • In the constructor, bind the layout file

    public class MyView extends ConstraintLayout {    
    	
          private String text;    
    	private Drawable image;   
    	private TextView textView;  
    	private ImageView imageView;  
    
          public MyView(Context context) {    
    	      this(context, null);  
          }  
    
          public MyView(Context context, AttributeSet attrs) {     
    	      this(context, attrs, -1);  
          }   
    
          public MyView(Context context, AttributeSet attrs, int defStyleAttr) {        		
                super(context, attrs, defStyleAttr);     
    	      //get layout       
    	      inflate(context, R.layout.my_view, this);     
    	      textView = findViewById(R.id.text);     
    	      imageView = findViewById(R.id.image);     
    
    	      }  
    	
    	public void setText(String text){     
    	      this.text = text;    
    	      textView.setText(text);  
    	}   
    
    	public void setImage(Drawable drawable){    
    		this.image = drawable;       
    		this.imageView.setImageDrawable(drawable);  
    	}
    }
    
3. Set the properties of the combined control

Under the values ​​file, create a new attrs.xml to declare your own attributes and attribute types. The name is the class name of the custom control, the name of attr is the attribute name, and the format is the attribute type (the picture is the object reference).

<?xml version="1.0" encoding="utf-8"?>
<resources>    
	<declare-styleable name="MyView" >        
		//custom properties        
		<attr name="myText" format="string"/>        
		<attr name="myImage" format="reference"/>    
	</declare-styleable>
</resources>

Then, to parse this custom attribute in the code, the xml parsing defined by yourself cannot be parsed.

public MyView(Context context, AttributeSet attrs, int defStyleAttr) {    	
	super(context, attrs, defStyleAttr);    
	//1. Get the layout    
	inflate(context, R.layout.my_view, this);   
	textView = findViewById(R.id.text);    
	imageView = findViewById(R.id.image); 
    
	//2. Get properties   
	TypedArray typedArray; 
	typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyView); 
    
    //get attribute value
	text = typedArray.getString(R.styleable.MyView_myText);    		
	textView.setText(text);   
    //set property value
	image = typedArray.getDrawable(R.styleable.MyView_myImage);    		
	imageView.setImageDrawable(image);  
    //Remember to recycle
	typedArray.recycle();
}

Custom attributes, in fact, because you want to reuse, so the display content of some controls should be dynamic. If you can configure it in xml like this textview, or use the code setText(), you can use custom attributes to configure it (purely personal conjecture). I suddenly thought that if you read the source code, the source code of textview, the properties of this textview are all done in the same way. I'll study it later.

4. Refer to the custom combination control

Add the following control reference to the main_activity.xml file:

<com.example.transition.MyView   
	android:layout_width="wrap_content"  
	android:layout_height="wrap_content"  
	app:myImage="@drawable/tol"  
	app:myText="Combination controls"/>

Then, run it and see the effect. Then the image and text are combined into a control. But there should be a lot of details that need to be considered to make it a really perfectly usable view.

Posted by jcrocker on Tue, 31 May 2022 16:22:18 +0530