Home PC Games Linux Windows Database Network Programming Server Mobile  
  Home \ Programming \ Drawing from the Android source code analysis View     - Change the kernel boot sequence after CentOS 7 kernel upgrade (Linux)

- Android design patterns - state mode (Programming)

- Linux account management add relevant directives (Linux)

- Ubuntu ADSL dial-up Internet access (Linux)

- Linux scp remote file copy (Linux)

- xCAT deployment (Linux)

- Caffe install under Ubuntu 14.04 64bit (Linux)

- LVM management parameters commonly used commands explained in detail (Linux)

- Linux operating system Study Notes (Linux)

- Using Java arrays implement sequential stack (Programming)

- Linux security configuration (Linux)

- Seven kinds of DDoS attack methods and techniques Defensive (Linux)

- Based kubernetes Construction Docker Cluster Management Comments (Server)

- Hibernate Performance Optimization of reusing SessionFactory (Programming)

- Linux kernel panic (because glibc result) Repair (Linux)

- Hadoop virtualization performance comparison and tuning experience (Server)

- Linux installation Jetty deployment under RedHat5 8 (Linux)

- Configuration based on open source Lucene Java development environment (Server)

- Linux automatically install service components and optimize the kernel parameters (Linux)

- Oracle Data File Management (Database)

  Drawing from the Android source code analysis View
  Add Date : 2018-11-21      
  During the development process, we often customize View. It is a fundamental part of the user interaction component, responsible for displaying images and processing event, as is usually the custom component base class inheritance. So today through source code to analyze carefully how the View is created and what happens during the drawing process.


First, overloads View public constructor there are four:

View (Context context) when the code view is created by using this constructor, through the context parameters, you can get to the topic, the resources needed and so on.

View (Context context, AttributeSet attrs) When creating a layout view through xml files using this constructor calls the constructor three parameters.

View (Context context, AttributeSet attrs, int defStyleAttr) Create view by xml layout files, and use specified in the properties of the style. The constructor of this view allows its subclasses use when you create your own style. Call the constructor of the next four parameters.

View (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) The constructor can create a view by xml layout file, you can use theme resource file attributes or style specified style.


Context: contextual information view operation, which you can get to the current theme, resource files and other information.

AttributeSet: xml layout view files under specified tag attributes.

defStyleAttr: a current theme of the property, which includes a resource file reference pointing theme of style. The default value is 0.

defStyleRes: a style resource file marked to indicate the style ID, when the value is 0 or can not find a corresponding theme resources when the default value.

In summary, the single argument constructor to create a view from the code, the remaining four are calling the constructor argument to create a view based on xml layout file. We can specify property values in different places, for example:

attrs values directly specified in the xml tag, can be obtained from the AttributeSet.

By specifying the properties in the label "style" in the resource file.

Default defStyleAttr.

Default defStyleRes.

The default value of the current theme.

Code constructor too long, not posted here, the work is mainly: Get the system-defined properties, and then view the property value of the member variable initialization and events.

Under normal circumstances, our custom view when rewriting the constructor, if only to create a code from the actual situation, only to achieve a single parameter can be used. If you need to create a layout from the xml file, you need to implement a single parameter, and a multi-parameter just fine, because the default multi-parameter constructor is called with four parameters; and then get into the custom attributes are processed on OK.

At this point, create, and view the initialization is completed, and then start drawing view work. So how to view Android system to draw it?


Get in activity to focus, it will request Android Framework based on its layout file draw, you need to provide the root activity depicted in the layout file, and then the tree structure of the layout while traversing the side draw. As we all know, is a subclass of View ViewGroup, it can have several sub-view, it's a lot of action and the same view, the difference is ViewGroup responsible for drawing its child nodes, and is responsible for drawing its own view. Entire traversal from top to bottom, throughout the process, you need to measure the size (measure function) and location (layout function), then paint. Here we look at how the work carried out:

Size Determination

In Android, all view is organized into a tree structure, the main work of the topmost measure is responsible for recursive measure the size of the entire view of the tree structure, the actual width and height are each View control is determined by the parent view and the view itself of.

Prior to study the source code, I'll start a whole before the recursive call at the whole process. Starting from the root view, using the method of calculation for the entire measure of the size of the tree view, onMeasure method is called sub-view in the process. In onMeasure were two main tasks:

Call setMeasuredDimension set view their size (mMeasureWidth and mMeasuredHeight), specific see below.

If this view is ViewGroup, you will need to continue its recursive calls ViewGroup onMeasure method to calculate the size of the sub-view.

Root view is usually a ViewGroup, you need to calculate the size of the sub-view. First, get to all child view, and then call measureChildWithMargins method to calculate the size of the sub-view. The measure is called the sub-view method in this method. Here we look at the specific source.

First, determine the size of the measure in view of the process. This type of method is defined as final, can not be overridden by subclasses. Has a static inner class MeasureSpec encapsulates the parent view to be passed to the child View layout parameters, the size and composition together in View mode. size is the size, mode schematic. (In fact, an int value represented two high mode, low 30 indicates size) mode There are three modes:

UNSPECIFIED: Parent view does not specify the size of the sub-view, can be arbitrary view according to the size of the developer needs.

EXACTLY: Parent view strictly specify the size of the sub-view

AT_MOST: child view size does not exceed this value

public final void measure (int widthMeasureSpec, int heightMeasureSpec) {
        boolean optical = isLayoutModeOptical (this); // whether to use visual layout border
        if (optical! = isLayoutModeOptical (mParent)) {// When the view and its parent viewGroup on whether to adopt the visual border layout is inconsistent
            Insets insets = getOpticalInsets ();
            int oWidth = insets.left + insets.right;
            int oHeight = insets.top + insets.bottom;
            widthMeasureSpec = MeasureSpec.adjust (widthMeasureSpec, optical -oWidth:? oWidth);
            heightMeasureSpec = MeasureSpec.adjust (heightMeasureSpec, optical -oHeight:? oHeight);

        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray (2);

        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
                widthMeasureSpec! = mOldWidthMeasureSpec ||
                heightMeasureSpec! = mOldHeightMeasureSpec) {

            // First clears the measured dimension flag
            mPrivateFlags & = ~ PFLAG_MEASURED_DIMENSION_SET;

            resolveRtlPropertiesIfNeeded ();

            int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT -1?:
                    mMeasureCache.indexOfKey (key);
            if (cacheIndex <0 || sIgnoreMeasureCache) {
                // Measure ourselves, this should set the measured dimension flag back
                onMeasure (widthMeasureSpec, heightMeasureSpec);
                mPrivateFlags3 & = ~ PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
            } Else {
                long value = mMeasureCache.valueAt (cacheIndex);
                // Casting a long to int drops the high 32 bits, no mask needed
                setMeasuredDimensionRaw ((int) (value >> 32), (int) value);
                mPrivateFlags3 | = PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;

            // Flag not set, setMeasuredDimension () was not invoked, we raise
            // An exception to warn the developer
                throw new IllegalStateException ( "onMeasure () did not set the"
                        + "Measured dimension by calling"
                        + "SetMeasuredDimension ()");

            mPrivateFlags | = PFLAG_LAYOUT_REQUIRED;

        mOldWidthMeasureSpec = widthMeasureSpec;
        mOldHeightMeasureSpec = heightMeasureSpec;

        mMeasureCache.put (key, ((long) mMeasuredWidth) << 32 |
                (Long) mMeasuredHeight & 0xffffffffL); // suppress sign extension

Method receives two parameters widthMeasureSpec and heightMeasureSpec view showing the width and height, is calculated by one level after passing over the parent view. Measurements carried out in view of the size of the standard red onMeasure method. In the custom view when we often need to override this method, according to the size of the incoming and view its contents to set the final size view display.

protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension (getDefaultSize (getSuggestedMinimumWidth (), widthMeasureSpec),

getDefaultSize (getSuggestedMinimumHeight (), heightMeasureSpec));


When overriding this method, we need to call this method to store setMeasuredDimension measure has good size (where default getDefalutSize), only after the call through this method, in order to obtain the size and the method by getMeasuredWidth getMeasuredHeight methods. At the same time, we must ensure that the resulting size of not less than the minimum size view. We need to note that, setMeasuredDimension method must be called OnMeasure process, otherwise it will throw an exception.

OK, measure method so far completed. However, we can discover the true measure of the size of the view does not work in this method is carried out, there is only one measurement framework, be judged according to a variety of situations, to complete the necessary steps. These steps are necessary and can not be changed developers, need custom work done on the onMeasure by the developer according to the situation. This will ensure the rendering process execution, and flexible to meet the various needs, is typical of the template method pattern.

Since more than one child may view the next parent view, so the measure method not only once, but to get all the child view in the parent view (viewGroup), and then call the measure traversal method of sub-view.


When the size of the view has been set up, then need to determine the position in view of the parent view, that is reasonable in view of the handle position. Because it contains only ViewGroup child view, so in general we are talking about the parent view, certainly in said ViewGroup. Complete the layout of the work is divided into two parts, it is a recursive implementation:

1. Call setFrame set the View view is the parent view coordinates layout method.

2. If the view is ViewGroup type, then call its onLayout Complete sub-view layout work.

Let's look at a specific source, the parent view called layout view of the sub-method:

public void layout (int l, int t, int r, int b) {
        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT)! = 0) {
            onMeasure (mOldWidthMeasureSpec, mOldHeightMeasureSpec);
            mPrivateFlags3 & = ~ PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;

        int oldL = mLeft;
        int oldT = mTop;
        int oldB = mBottom;
        int oldR = mRight;
        // Determine whether the layout if there have been changes, the need to redraw.
        boolean changed = isLayoutModeOptical (mParent)?
                setOpticalFrame (l, t, r, b): setFrame (l, t, r, b);
        // Needs to be redrawn. if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
            onLayout (changed, l, t, r, b); // determine the position in the layout view
            mPrivateFlags & = ~ PFLAG_LAYOUT_REQUIRED;

            ListenerInfo li = mListenerInfo;
            if (li! = null && li.mOnLayoutChangeListeners! = null) {
                ArrayList < OnLayoutChangeListener > listenersCopy =
                        (ArrayList < OnLayoutChangeListener >) li.mOnLayoutChangeListeners.clone ();
                int numListeners = listenersCopy.size ();
                for (int i = 0; i < numListeners; ++ i) {
                    listenersCopy.get (i) .onLayoutChange (this, l, t, r, b, oldL, oldT, oldR, oldB);

        mPrivateFlags & = ~ PFLAG_FORCE_LAYOUT;
        mPrivateFlags3 | = PFLAG3_IS_LAID_OUT;

This method takes four parameters are sub-view relative to the parent view in terms of the vertical and horizontal position. However, we found that a method call to onLayout default implementation is empty. This is because in a position to determine the layout of the view that the operation should be done according to their characteristics Layout. Define any layout should rewrite its onLayout method, and in which the set position of the sub-view.


After making the determination Ends size and positioning, we can finally start drawing up. Here work is still done by recursively. view call the draw method to draw, which calls onDraw to draw itself, if there is need to call the child view dispatchDraw to draw child view.

Draw call the draw method, divided into a total of six steps:

Draw background
If desired, save the canvas edge preparation level of desalination.
Draw the contents of the view
Draw child view
If desired, the draw and fade the edges of the storage layer.
Drawing decorative parts, such as scroll bars.
public void draw (Canvas canvas) {
        final int privateFlags = mPrivateFlags;
        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                (MAttachInfo == null || mAttachInfo.mIgnoreDirtyState!);
        mPrivateFlags = (privateFlags & ~ PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
        // Step 1, draw background
        int saveCount;

        if (! dirtyOpaque) {
            drawBackground (canvas);

        // If not, skip steps 2 and 5
        final int viewFlags = mViewFlags;
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) = 0!;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) = 0!;
        if (! verticalEdges &&! horizontalEdges) {
            // Step 3, draw content
            if (! dirtyOpaque) onDraw (canvas);

            // Step 4, sub-view drawing
            dispatchDraw (canvas);

            // Step 6, draw decorative part
            onDrawScrollBars (canvas);

            if (mOverlay! = null &&! mOverlay.isEmpty ()) {
                . MOverlay.getOverlayView () dispatchDraw (canvas);

            // carry out


We chose a conventional drawing process, not covered 2,5 step.

First, draw a background pattern drawBackground call:

private void drawBackground (Canvas canvas) {
        final Drawable background = mBackground;
        // Get the current view in the background, is a drawable objects if (background == null) {

        if (mBackgroundSizeChanged) {// determine whether the change in the size of the background, set the background is the boundary
            background.setBounds (0, 0, mRight - mLeft, mBottom - mTop);
            mBackgroundSizeChanged = false;
            mPrivateFlags3 | = PFLAG3_OUTLINE_INVALID;

        // Attempt to use a display list if requested.
        if (canvas.isHardwareAccelerated () && mAttachInfo! = null
                && MAttachInfo.mHardwareRenderer! = Null) {
            mBackgroundRenderNode = getDrawableRenderNode (background, mBackgroundRenderNode);

            final RenderNode displayList = mBackgroundRenderNode;
            if (displayList! = null && displayList.isValid ()) {
                setBackgroundDisplayListProperties (displayList);
                ((HardwareCanvas) canvas) .drawRenderNode (displayList);
      // Call drawable object drawing method to complete the drawing
        final int scrollX = mScrollX;
        final int scrollY = mScrollY;
        if ((scrollX | scrollY) == 0) {
            background.draw (canvas);
        } Else {
            canvas.translate (scrollX, scrollY);
            background.draw (canvas);
            canvas.translate (-scrollX, -scrollY);

The third step is to call a method drawn onDraw view content, due to different content of view, it is necessary to rewrite the subclass.

The fourth step is to draw the child view, there is still need for the current layout of dispatchDraw method to complete the draw for each of the sub-view.

The sixth step, draw a scroll bar.

Under normal circumstances, our custom view, replication onDraw method to draw the view we defined content.

to sum up

By studying the view class source code, we can see that, in view of the whole drawing process, we need to complete the determination of the size, layout, location, drawing these three steps. Android in the design process, the fixed template for the process design methods can not be changed, however the case may be required depending on the contents will be given to developers to complete rewrite, you can call in the template method. This design is to ensure the integrity of the entire process, and gave the development work has brought flexible. Meanwhile, in the class according to the different circumstances they define different flag, drawn to meet the needs of different circumstances, have the opportunity to study these specific particular significance flag of.
- Oracle ORA-01089 failure analysis (Database)
- Do not enter password login ssh (Server)
- Eight sorting algorithm implemented in Python (Programming)
- Linux remote landing system (Linux)
- Xshell key authentication mechanism using a remote login Linux (Linux)
- Elixir: the future of programming languages (Programming)
- Process monitoring tools Supervisor start MongoDB (Database)
- Oracle 11g Export guide problem not an empty table (Database)
- Ubuntu users install the video driver Nvidia Driver 334.21 (Linux)
- Ftp user to create multiple virtual machines to support different access rights Examples (Server)
- Android Studio installed in Ubuntu 15.04 (Linux)
- ApacheDS configuration of users and user groups to achieve SSO (Server)
- Detailed steps - GAMIT solver (Linux)
- Yii2 Advanced Version Copy New Project Problem Solved (Programming)
- Java 8 Lambda principle analysis (Programming)
- Oracle Database import and export combat (Database)
- Port Telnet command to detect the remote host is turned on (Linux)
- Character Encoding notes: ASCII, Unicode and UTF-8 (Linux)
- C ++ virtual functions Classic Insights (Programming)
- Using Java program determines whether it is a leap year (Programming)
  CopyRight 2002-2022 newfreesoft.com, All Rights Reserved.