Drawing process of Android-UI control and specific operation of custom control

Posted by essexboyracer on Sun, 14 Jul 2019 22:04:41 +0200

  View View View is a very important component of Android applications. It is not only the basic unit of the application interface, but also the most direct object to interact with users. View View, as the basic element of the interface, is managed by View System.

  In Android, view controls are divided into two main categories, one is single control View, the other is ViewGroup, which can contain and manage sub-controls. In an interface layout, the nesting and combination of ViewGroup and View constitute a control tree, which is drawn on the screen through a series of processes to form a complete use. User Interface.

   View is the most basic UI class. Almost all controls inherit from View. Generalized View refers to a single control other than ViewGroup, such as TextView, CheckBox, Button, EditText, RadioButton, which manages their own rendering and event handling. ViewGroup is a subclass of View and exists as a container of View control. ViewGroup can control the display level and location of each subview, and can process, intercept or distribute interactive events such as focus acquisition and touch.

  View rendering is mainly divided into three steps: Measure, Layout and Draw.

  In Mesure operation, the distribution of measurement operation is completed by ViewGroup. ViewGroup traverses and distributes measurement operation to the child nodes. In the specific measurement process, the width and height of the child nodes are calculated according to the MeasureSpec of the parent node and LayoutParams of the child node. Finally, the width and height of the parent container are sorted out. The volume measurement method can also be set by rewriting the onMeasure method.

  Next, through the Layout process, we can determine the specific location of each View in the parent container. Similarly, we can customize the specific layout process through the onLayout method.

  Finally, it enters the drawing process of Draw. According to the specific layout parameters obtained in the first two steps, each control is drawn in drawing function. The order of drawing is background-control content-sub-control drawing-drawing-edge and scroll bar decorations.

  Generally speaking, control drawing is done on the control tree. ViewGroup distributes it to sub-View to complete their own measurement and layout operations. Finally, the root node starts to draw, and finally forms a complete interface.

  Finally, choose a specific example to observe the rendering process of View.

  First, let's look at the specific drawing process of TextView:

  

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int width;
        int height;
        
        ......
        
        setMeasuredDimension(width, height);
    }

  The incoming MeasureSpec is a 32-bit integer with two high bits representing the measurement mode and 30 low bits representing the size of the specification. This integer specifies how the control will perform the specific measurement. Finally, the width and height of measurement results are set by using the updated width and height. The main function of this function is to calculate whether margin/padding or not causes extra width and height, reserve space when necessary, and determine the size of view.

@Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (mDeferScroll >= 0) {
            int curs = mDeferScroll;
            mDeferScroll = -1;
            bringPointIntoView(Math.min(curs, mText.length()));
        }
    }

  Here the onLayout function of the parent class is called

/**
 * Called from layout when this view should
 * assign a size and position to each of its children.
 *
 * Derived classes with children should override
 * this method and call layout on each of
 * their children.
 * @param changed This is a new size or position for this view
 * @param left Left position, relative to parent
 * @param top Top position, relative to parent
 * @param right Right position, relative to parent
 * @param bottom Bottom position, relative to parent
 */
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}

 You can see the annotation of the function in the View, and you can see that the main function of the function is to assign the position and size of the view for the next drawing.

@Override
protected void onDraw(Canvas canvas) {
    restartMarqueeIfNeeded();

    // Draw the background for this view
    super.onDraw(canvas);
    
    ......
    
    mTextPaint.setColor(color);
    mTextPaint.drawableState = getDrawableState();
    
    ......
    
    layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
    ......
    
    }

 The onDraw function is invoked when the view needs to be rendered, setting specific parameters such as brushes, and calling draw for specific drawing.

/**
 * Draw this Layout on the specified canvas, with the highlight path drawn
 * between the background and the text.
 *
 * @param canvas the canvas
 * @param highlight the path of the highlight or cursor; can be null
 * @param highlightPaint the paint for the highlight
 * @param cursorOffsetVertical the amount to temporarily translate the
 *        canvas while rendering the highlight
 */
public void draw(Canvas canvas, Path highlight, Paint highlightPaint,
        int cursorOffsetVertical) {
    final long lineRange = getLineRangeForDraw(canvas);
    int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
    int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
    if (lastLine < 0) return;

    drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical,
            firstLine, lastLine);
    drawText(canvas, firstLine, lastLine);
}

  Drawing functions for background and specific text are called in draw method. 

  All in all, we can rewrite these methods to complete our control customization. 


Topics: Android