This is the 20th day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021

First, Android control architecture

Controls in Android are roughly divided into two categories: ViewGroup controls and View controls. A ViewGroup control as a parent control can package several View controls and manage the View controls it contains. Through ViewGroup, the whole interface forms a tree structure, that is, the control tree. Take a look at the Android interface architecture below:

As you can see from the diagram, each Activity contains a Window object, which in Android is usually implemented by PhoneWindow. PhoneWindow sets a DecorView as the root View of the entire application Window. On display it splits the screen into two parts, a TitleView and a ContentView, which is a Framelayout with the ID content, so we normally setContentView in the onCreate method.

2. View measurement

We all know that when we customize a control, we measure the control in the onMeasure() method. The Android system provides us with a powerful class called MeasureSpec that helps us measure the View. MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec Measurement modes can be divided into three categories:

  • EXACTLY: EXACTLY measured mode, usually because we specify the size of the control or set it to the match_parent property.
  • AT_MOST: indicates the maximum value mode. When the control size is not specified, the control size changes with the content, that is, when the wrAP_content property is set.
  • UNSPECIFIED: This attribute is odd, as it does not specify the measurement mode, and the View is UNSPECIFIED. This attribute is typically used when drawing custom views.

The View class’s default onMeasure() method only supports EXACTLY mode, so it is the default exact measure mode if you do not override the onMeasure() method when customizable controls. Normally we override the onMeasure method to specify it. If we look at the source code, we can see that setMeasuredDimension(int measuredWidth,int measuredHeight) is finally called to set the measuredWidth and height. Here is a simple example of a test:

	@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if(heightMode == MeasureSpec.AT_MOST){
            heightSize = mDisplayMetrics.densityDpi * 30;
        }
        if(widthMode == MeasureSpec.AT_MOST){
            widthSize = mDisplayMetrics.densityDpi * 300;
        }
        setMeasuredDimension(widthSize, heightSize);
    }
Copy the code

From the simple example above, we can see that we first get the measurement mode we need and then specify it according to our requirements. It’s that simple. It’s that easy. The specific effect, we can simply practice.

3. View rendering

We know that in drawing the View, we’re drawing the view in the onDraw() method. The onDraw method gives us a Canvas object to draw what we need. Let’s look at creating a Canvas object.

	Canvas canvas = new Canvas(bitmap);
Copy the code

When creating a Canvas object, we usually bind a bitmap object to the Canvas. This process is called loading the Canvas. This bitmap stores information about all pixels drawn on the Canvas board, so when you use the canvas for the drawXXX method, the information is on the Bitmap.

Iv. Measurement of ViewGroup

In the previous analysis, we know that the ViewGroup contains many View objects, so the size of the ViewGroup is also specified or set to wrap_content, which is controlled by the size of the child control. When set to wrap_content, The size of the ViewGroup is measured by the internal traversal of the child Views. When the child views are measured, execute the View Layout method to place them.

ViewGroup rendering

A ViewGroup usually doesn’t need to be drawn because it has nothing to draw. If you don’t specify the background color of the ViewGroup, the onDraw() method of the ViewGroup will not be called. However, the ViewGroup uses the dispatchDraw() method to draw its subview, again iterating through all the subviews and calling the subview’s draw method.

6. Customize View

We all know that custom controls can make an application shine when used properly, but overusing custom Views can backfire. A familiar, easy-to-use control tests a good control. When customizing a View, there are several important callback methods:

  • OnFinishInflate () : callback after loading a component from XML
  • OnSizeChanged () : Callback when component size changes.
  • OnMeasure () : calls back the method to measure.
  • OnLayout () : Calls back to this method for layout of the control.
  • OnTouchEvent () : Listens for the touch event callback of the control.

In general, custom controls fall into the following three categories:

  • By extending existing controls; This kind of control is mainly our inheritance system for extension.
  • Implement new controls by combining controls.
  • Rewrite to implement new, brand new controls.

6.1 Extensions to existing controls

Instead of enumerating the examples in the book, I will write an example for you. Gravity is set to center by default, and Gravity needs to be left to get focus. Therefore, it is not possible to rewrite an EditText for this small function, so we can extend the controls here. The code is as follows:

public class IOSEditText extends EditText { public IOSEditText(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { if(focused){ setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); }else{ setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL); }}}Copy the code

This is a simple example of extending an existing control.

6.2 Creating a Composite Control

Composite controls are easy to use. For example, in a page layout, there are many duplicate layout structures. At this time, we can extract them, make them into composite controls, and then use them, which can also reduce the layout structure of the code. Here are some things to know:

  • Custom attributes
  • Define the callback interface

####6.3 Rewrite View to implement a new control here is our pure custom control. The specific process is also introduced above, mainly how to achieve the drawing. Can refer to a few basic tutorials on the net to learn, recommend hongyang and love elder brother’s custom control tutorial, very good, 100 praise.

7. Customize ViewGroup

The basic process of customizing a ViewGroup has been described briefly.

8. Analysis of event interception mechanism

In custom controls, event distribution is important. Online introduction is also a lot, recommend several addresses: Android programming under the Touch event distribution and consumption mechanism

Android:30 minutes to understand the Touch event distribution mechanism

So far, basic knowledge point enumerated come out, compare study!