[ Web Proxy ]
URL:
Viewing: http://developer.android.com/develop/ui/compose/layouts/constraints-modifiers [Back]  [Original]

Constraints and modifier order  |  Jetpack Compose  |  Android Developers Skip to main content
Essentials Design & Plan Develop Google Play Blog
Search:
Android Studio
Android Developers [Android Developers]

Constraints and modifier order Stay organized with collections Save and categorize content based on your preferences.

In Compose, you can chain multiple modifiers together to change the look and feel of a composable. These modifier chains can affect the constraints passed to composables, which define width and height bounds.

This page describes how chained modifiers affect constraints and, in turn, the measurement and placement of composables.

Modifiers in the UI tree

To understand how modifiers influence each other, it's helpful to visualize how they appear in the UI tree, which is generated during the composition phase. For more information, see the Composition section.

In the UI tree, you can visualize modifiers as wrapper nodes for the layout nodes:

Code for composables and modifiers, and their visual representation as a UI tree. [Code for composables and modifiers, and their visual representation as a UI tree.] Figure 1. Modifiers wrapping layout nodes in the UI tree.

Adding more than one modifier to a composable creates a chain of modifiers. When you chain multiple modifiers, each modifier node wraps the rest of the chain and the layout node within. For example, when you chain a clip and a size modifier, the clip modifier node wraps the size modifier node, which then wraps the Image layout node.

In the layout phase, the algorithm that walks the tree stays the same, but each modifier node is visited as well. This way, a modifier can change the size requirements and placement of the modifier or layout node that it wraps.

As shown in Figure 2, the implementation of the Image and Text composables themselves consists of a chain of modifiers wrapping a single layout node.

The implementations of Row and Column are layout nodes that describe how to lay out their children.

The tree structure from before, but now each node is just a simple layout, with a lot of modifier wrapping nodes around it. [The tree structure from before, but now each node is just a simple layout, with a lot of modifier wrapping nodes around it.] Figure 2. The same tree structure as in Figure 1, but with composables in the UI tree visualized as chains of modifiers.

To summarize:

The following sections describe how to use this mental model to reason about modifier chaining and how it influences the size of composables.

Constraints in the layout phase

The layout phase follows a three-step algorithm to find each layout node's width, height, and x, y coordinate:

  1. Measure children: A node measures its children, if any.
  2. Decide own size: Based on those measurements, a node decides on its own size.
  3. Place children: Each child node is placed relative to a node's own position.

Constraints help find the right sizes for the nodes during the first two steps of the algorithm. Constraints define the minimum and maximum bounds for a node's width and height. When the node decides on its size, its measured size should fall within this size range.

Types of constraints

A constraint can be one of the following:

Bounded constraints of different sizes within a container. [Bounded constraints of different sizes within a container.] Figure 3. Bounded constraints. Unbounded constraints that have the width and height set to infinity. The constraints extend beyond the container. [Unbounded constraints that have the width and height set to infinity. The constraints extend beyond the container.] Figure 4. Unbounded constraints. Exact constraints that conform to an exact size requirement within the container. [Exact constraints that conform to an exact size requirement within the container.] Figure 5. Exact constraints. Two containers that show combinations of bounded and unbounded constraints and exact widths and heights. [Two containers that show combinations of bounded and unbounded constraints and exact widths and heights.] Figure 6. Combinations of bounded and unbounded constraints and exact widths and heights.

The next section describes how these constraints are passed from a parent to a child.

How constraints are passed from parent to child

During the first step of the algorithm described in Constraints in the layout phase, constraints are passed down from parent to child in the UI tree.

When a parent node measures its children, it provides these constraints to each child to let them know how big or small they're allowed to be. Then, when it decides its own size, it also adheres to the constraints that were passed in by its own parents.

At a high level, the algorithm works in the following way:

  1. To decide the size it actually wants to occupy, the root node in the UI tree measures its children and forwards the same constraints to its first child.
  2. If the child is a modifier that does not impact measurement, it forwards the constraints to the next modifier. The constraints are passed down the modifier chain as-is unless a modifier that impacts measurement is reached. The constraints are then re-sized accordingly.
  3. Once a node is reached that doesn't have any children (referred to as a "leaf node"), it decides its size based on the constraints that were passed in, and returns this resolved size to its parent.
  4. The parent adapts its constraints based on this child's measurements, and calls its next child with these adjusted constraints.
  5. Once all children of a parent are measured, the parent node decides on its own size and communicates that to its own parent.
  6. This way, the whole tree is traversed depth-first. Eventually, all the nodes have decided on their sizes, and the measurement step is completed.

For an in-depth example, see the Constraints and modifier order video.

Modifiers that affect constraints

You learned in the previous section that some modifiers can affect constraint size. The following sections describe specific modifiers that impact constraints.

The size modifier

The size modifier declares the preferred size of the content.

For example, the following UI tree should be rendered in a container of 300dp by 200dp. The constraints are bounded, allowing widths between 100dp and 300dp, and heights between 100dp and 200dp:

A portion of a UI tree with the size modifier wrapping a layout node, and the
  representation of the bounded constraints set by the size modifier in a container. [A portion of a UI tree with the size modifier wrapping a layout node, and the representation of the bounded constraints set by the size modifier in a container.] Figure 7. Bounded constraints in the UI tree and its representation in a container.

The size modifier adapts incoming constraints to match the value passed to it. In this example, the value is 150dp:

The same as Figure 7, except with the size modifier adapting incoming constraints to match the value passed to it. [The same as Figure 7, except with the size modifier adapting incoming constraints to match the value passed to it.] Figure 8. The size modifier adjusting constraints to 150dp.

If the width and height are smaller than the smallest constraint bound, or larger than the largest constraint bound, the modifier matches the passed constraints as closely as it can while still adhering to the constraints passed in:

Two UI trees and their corresponding representations in containers. In the first, the
  size modifier accepts the incmoing constraints; in the second, the size modifier adapts to the
  too-large constraints as closely as possible, resulting in constraints that fill the container. [Two UI trees and their corresponding representations in containers. In the first, the size modifier accepts the incmoing constraints; in the second, the size modifier adapts to the too-large constraints as closely as possible, resulting in constraints that fill the container.] Figure 9. The size modifier adhering to the passed constraint as closely as possible.

Note that chaining multiple size modifiers does not work. The first size modifier sets both the minimum and maximum constraints to a fixed value. Even if the second size modifier requests a smaller or larger size, it still needs to adhere to the exact bounds passed in, so it won't override those values:

A chain of two size modifiers in the UI tree and its representation in a container,
  which is the result of the first value passed in and not the second value. [A chain of two size modifiers in the UI tree and its representation in a container, which is the result of the first value passed in and not the second value.] Figure 10. A chain of two size modifiers, in which the second value passed in (50dp) does not override the first value (100dp).

The requiredSize modifier

Use the requiredSize modifier instead of size if you need your node to override the incoming constraints. The requiredSize modifier replaces the incoming constraints and passes the size you specify as exact bounds.

When the size is passed back up the tree, the child node will be centered in the available space:

The size and requiredSize modifier chained in a UI tree, and the corresponding
  representation in a container. The requiredSize modifier constraints override the size modifier
  constraints. [The size and requiredSize modifier chained in a UI tree, and the corresponding representation in a container. The requiredSize modifier constraints override the size modifier constraints.] Figure 11. The requiredSize modifier overriding incoming constraints from the size modifier.

The width and height modifiers

The size modifier adapts both the width and height of the constraints. With the width modifier, you can set a fixed width but leave the height undecided. Similarly, with the height modifier, you can set a fixed height, but leave the width undecided:

Two UI trees, one with the width modifier and its container representation and the other
  with the height modifier and its representation. [Two UI trees, one with the width modifier and its container representation and the other with the height modifier and its representation.] Figure 12. The width modifier and height modifier setting a fixed width and height, respectively.

The sizeIn modifier

The sizeIn modifier lets you set exact minimum and maximum constraints for width and height. Use the sizeIn modifier if you need fine-grained control over the constraints.

A UI tree with the sizeIn modifier with minimum and maximum widths and heights set,
  and its representation within a container. [A UI tree with the sizeIn modifier with minimum and maximum widths and heights set, and its representation within a container.] Figure 13. The sizeIn modifier with minWidth, maxWidth, minHeight, and maxHeight set.

Examples

This section shows and explains the output from several code snippets with chained modifiers.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .size(50.dp)
)

This snippet produces the following output:

A blue square that fills its parent container. [A blue square that fills its parent container.] Figure 14. The Image fills the maximum size as a result of the modifier chain.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .wrapContentSize()
        .size(50.dp)
)

This snippet produces the following output:

A small blue square centered within its parent container. [A small blue square centered within its parent container.] Figure 15. The Image is centered and sized to 50dp.

By combining just three modifiers, you can define a size for the composable and center it in its parent.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .clip(CircleShape)
        .padding(10.dp)
        .size(100.dp)
)

This snippet produces the following output:

A circular shape that is incorrectly clipped because of
       modifier order. [A circular shape that is incorrectly clipped because of modifier order.] Figure 16. An incorrectly clipped shape due to modifier order.
Modifiers
Custom modifiers

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2026-08-14 UTC.

[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2026-08-14 UTC."],[],[]]

Web Proxy Viewer  |  New URL  |  Original Page