Mobile Development 12 min read

Understanding Android ViewGroup: Concepts, Drawing Process, Measure/Layout/Draw, and Custom Implementation

This article explains the fundamentals of Android ViewGroup, its coordinate systems, the complete drawing pipeline from Activity creation to SurfaceFlinger, details the Measure‑Layout‑Draw phases, and provides a step‑by‑step guide to building a custom ViewGroup with custom LayoutParams and practical examples.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Understanding Android ViewGroup: Concepts, Drawing Process, Measure/Layout/Draw, and Custom Implementation

Concept

ViewGroup is a special container view that can hold other views; it serves as the base class for all layout containers. It defines ViewGroup.LayoutParams for layout parameters. To function, a ViewGroup must override onMeasure to measure its children and itself, and implement onLayout to position the children.

Drawing Principle

Android uses a top‑left origin coordinate system. The article shows the screen coordinate system and the internal View coordinate system with diagrams.

From the diagrams, the overall display process can be summarised as:

ActivityManagerService creates an Activity thread and activates an activity.

Instrumentation creates the activity instance.

The activity is attached to a newly created PhoneWindow, obtaining a WindowManager instance.

setContentView adds the UI views to PhoneWindow's ContentParent.

When Activity.makeVisible is called, the root view (DecorView) is added to WindowManager, which creates a corresponding ViewRoot.

Each ViewRoot owns a Surface; SurfaceFlinger creates the graphics memory and composes all view surfaces according to Z‑order for display.

If drawing directly on Canvas, the Surface is used; otherwise, ViewRoot notifies the SurfaceFlinger to merge surfaces and present them on the screen.

The actual rendering is handled by WindowManager and SurfaceFlinger, not by the Activity itself, which is why developers often use SurfaceView for high‑performance graphics such as games.

Drawing Process

The View tree traversal is performed in ViewRoot.performTraversals() , which decides whether to re‑measure, re‑layout, or redraw based on the current state.

Measure

During measurement, if layout_width or layout_height is match_parent or a fixed size, setMeasuredDimension() is called directly. For wrap_content , the ViewGroup iterates over all children, measures each, and calculates its own size based on the children’s dimensions and layout rules.

Key methods:

setMeasuredDimension(int measuredWidth, int measuredHeight) – sets the measured size of the ViewGroup.

getDefaultSize(int size, int measureSpec) – obtains the default size, usually derived from getSuggestedMinimumWidth() .

getSuggestedMinimumWidth() – returns the view's default width, which is mMinWidth if no background is set, otherwise the larger of mMinWidth and the background's minimum width.

Layout

The layout phase positions each child view. onLayout() is called after measurement, using the parent’s top‑left corner as the origin. The method sets each child’s frame via setOpticalFrame() or setFrame() , while the ViewGroup’s own position is already established.

Draw

During the draw phase, the ViewGroup iterates over its children and invokes each child’s onDraw() . Because a ViewGroup is primarily a container, it usually relies on the default implementation and does not perform additional drawing.

Practical Example

The article demonstrates a custom ViewGroup that arranges child views horizontally and automatically wraps to a new line when space runs out. It shows the overridden onMeasure and onLayout implementations, the XML layout file, and the runtime screenshot.

Common pitfalls discussed include:

Removing the first child does not trigger a layout change because the container height remains unchanged; removing several children does trigger a change.

Immediately adding the same number of children after removal may keep the change flag false, causing the new children not to appear; inserting a short delay solves the issue.

Custom LayoutParams

To support custom positioning (e.g., placing up to four children at the four corners), the article shows how to subclass MarginLayoutParams , override the method that creates LayoutParams, and use the margins in onMeasure and onLayout to compute the exact positions.

Key steps:

Extend ViewGroup and provide a constructor.

Override generateLayoutParams(AttributeSet attrs) to return a MarginLayoutParams instance.

In onMeasure , measure children, calculate the ViewGroup’s size (especially for wrap_content ) based on children dimensions and margins.

In onLayout , position each child according to its index (top‑left, top‑right, bottom‑left, bottom‑right) using the calculated margins.

Summary

Steps to create a custom ViewGroup

Extend ViewGroup and override the constructor.

Override onMeasure to measure children and set the ViewGroup’s measured width and height.

Implement onLayout to position the children.

Custom layout attributes for the container

Extend ViewGroup.LayoutParams (or MarginLayoutParams ) to define custom attributes.

Override the method that returns the custom LayoutParams.

Use the custom attributes in XML layout files.

Apply the custom LayoutParams inside onMeasure and onLayout .

References

https://blog.csdn.net/qq_36391075/article/details/77854541

https://www.jianshu.com/p/138b98095778

mobile developmentLayoutAndroidViewGroupCustom LayoutDrawMeasure
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.