Episode 3 of MAD Abilities: Compose Layouts and Modifiers
Within the earlier MAD Abilities article, you realized in regards to the three phases of Compose that rework knowledge into UI. We created a psychological mannequin to assist us purpose about our app’s design implementation. On this episode, we’ll use that psychological mannequin to be taught to purpose about modifier chaining and the way it influences the sizes of our composables.
For those who’ve acquired any questions so removed from this collection on Compose Layouts and Modifiers, we could have a reside Q&A session on March ninth. Depart a remark right here, on YouTube, or utilizing #MADCompose on Twitter to ask your questions.
You may also watch this text as a MAD Abilities video:
Keep in mind from final episode that we now have three phases of reworking knowledge into UI:
- Composition: What to point out
- Format: The place to position it
- Drawing: Tips on how to render it
Modifiers can have an effect on totally different phases. For instance, the measurement
and padding
modifier affect the scale and spacing of a composable through the structure section, and the clip
modifier influences the form of a composable through the draw section:
We additionally know that we are able to add multiple modifier to a composable, creating a sequence. Nevertheless, it isn’t at all times obvious how the totally different modifiers in these chains have an effect on one another.
Let’s begin with some workouts. For every of the next code snippets, attempt to determine which possibility could be the outcome of executing that snippet, possibility A or B:
Downside 1
/* Copyright 2023 Google LLC.
SPDX-License-Identifier: Apache-2.0 */Picture(
painterResource(R.drawable.frag),
contentDescription = null,
Modifier
.fillMaxSize()
.measurement(50.dp)
)
Downside 2
/* Copyright 2023 Google LLC.
SPDX-License-Identifier: Apache-2.0 */Picture(
painterResource(R.drawable.frag),
contentDescription = null,
Modifier
.fillMaxSize()
.wrapContentSize()
.measurement(50.dp)
)
Downside 3
/* Copyright 2023 Google LLC.
SPDX-License-Identifier: Apache-2.0 */Picture(
painterResource(R.drawable.frag),
contentDescription = null,
Modifier
.clip(CircleShape)
.padding(10.dp)
.measurement(100.dp)
)
Not precisely positive in regards to the solutions? You’ve come to the precise place then! Proceed studying to know extra. (psst, the solutions are on the finish of the weblog publish)
To learn to purpose about modifier order, we must be taught in regards to the position of Constraints
through the structure section.
Do not forget that within the final article we mentioned how the structure section follows a three-step algorithm to seek out every structure node’s width, top and x, y coordinate:
- Measure youngsters: A node measures its youngsters, if any.
- Determine personal measurement: Based mostly on these measurements, a node decides by itself measurement.
- Place youngsters: Every little one node is positioned relative to a node’s personal place.
Constraints assist discovering the precise sizes for our nodes through the first two steps of this algorithm. They’re minimal and most bounds for a node’s width and top. When the node decides on its measurement, its measured measurement ought to fall on this given measurement vary.
Constraints are handed down from mother or father to little one within the UI tree, throughout step one of the algorithm. When a mother or father node measures its youngsters, it gives these constraints to every little one to allow them to know the way huge or small they’re allowed to be. Then, when it decides its personal measurement, it additionally adheres to the constraints that have been handed in by its personal dad and mom.
Forms of constraints
Constraints might be bounded, indicating a minimal and a most width and top:
Constraints will also be unbounded, wherein case the node will not be constrained to any measurement. The utmost width and top bounds are then set to infinity:
Or constraints might be precise, asking the node to observe an actual measurement requirement. The minimal and most bounds are set to the identical worth:
In fact, mixtures of those are additionally legitimate, for instance bounding the width, whereas permitting for an unbounded most top, or setting an actual width however offering a bounded top:
To grasp how constraints are handed from mother or father to little one, and the way sizes are then resolved primarily based on these constraints, it’s finest to stroll by means of an instance. Nevertheless, that is a lot simpler to current in a video format, so I’d recommend you watch the chapter “an instance” of the MAD Abilities video:
By watching the video you must have an excellent understanding of how constraints have an effect on the scale of composables, and the way modifiers have an effect on these constraints. On this part we’ll take a better have a look at some particular modifiers and the way they impression constraints.
measurement
modifier
Let’s have a look at the next UI tree, that must be rendered in a container of 300dp
by 200dp
. The constraints are bounded, permitting widths between 100dp
and 300dp
, and heights between 100dp
and 200dp
.
The measurement
modifier adapts the incoming constraints to match the worth handed to it, for instance150dp
:
However what if the requested measurement is just too small or too huge? That’s, what if the width and top are smaller than the smallest constraint sure, or bigger than the biggest constraint sure?
On this case, the modifier will attempt to match the handed constraints as intently as it could possibly, whereas nonetheless adhering to the constraints handed in:
This additionally explains why chaining a number of measurement
modifiers doesn’t work. The primary measurement
modifier will set each the minimal and most constraints to a hard and fast worth, and although the second measurement
modifier requests a smaller or bigger measurement, it nonetheless wants to stick to the precise bounds handed in, so it won’t override these values:
requiredSize modifier
For those who do want your node to override the incoming constraints, you’ll be able to exchange the measurement
modifier with one other modifier known as requiredSize
. It should exchange the incoming constraints and go the scale you specify as an alternative, as precise bounds. Then, when the scale is handed again up the tree, the kid node can be centered within the accessible house:
width and top modifiers
In earlier examples we used a measurement
modifier, that adapts each width and top of the constraints. Nevertheless, we are able to additionally exchange these with the width
modifier, that units a fastened width however leaves the peak undecided. Or we are able to use the top
modifier, that units a fastened top however leaves the width undecided:
sizeIn modifier
For those who want fine-grained management over the constraints, and wish to adapt them to your precise wants, you should utilize the sizeIn
modifier:
Now that we realized about constraints and the way they affect measurements, let’s return to our authentic use instances and discover the precise options.
Downside 1
/* Copyright 2023 Google LLC.
SPDX-License-Identifier: Apache-2.0 */Picture(
painterResource(R.drawable.frag),
contentDescription = null,
Modifier
.fillMaxSize()
.measurement(50.dp)
)
Right here’s the answer:
- The
fillMaxSize
modifier adjustments the constraints to set each the minimal width and top to the utmost worth —300dp
in width, and200dp
in top. - So although the
measurement
modifier desires to make use of a measurement of50dp
, it nonetheless wants to stick to the incoming minimal constraints. And thus the scale modifier can even output the precise constraint bounds of300
by200
, successfully ignoring the worth offered within themeasurement
modifier. - The
Picture
follows these bounds and reviews a measurement of300
by200
, which is handed all the best way up.
Downside 2
/* Copyright 2023 Google LLC.
SPDX-License-Identifier: Apache-2.0 */Picture(
painterResource(R.drawable.frag),
contentDescription = null,
Modifier
.fillMaxSize()
.wrapContentSize()
.measurement(50.dp)
)
Right here’s the answer:
- The
fillMaxSize
modifier will nonetheless behave the identical, and adapt the constraints to set each the minimal width and top to the utmost worth —300dp
in width, and200dp
in top. - The
wrapContentSize
modifier resets the minimal constraints. So whereasfillMaxSize
resulted in fastened constraints,wrapContentSize
resets it again to bounded constraints. The next node can now take up the entire house once more, or be smaller than all the house. - The
measurement
modifier units the constraints to minimal and most bounds of50
. - The
Picture
resolves to a measurement of50
by50
, and themeasurement
modifier forwards that. - The
wrapContentSize
modifier has a particular property. It takes its little one, and places it within the middle of the accessible minimal bounds that have been handed to it. The scale it communicates to its dad and mom is thus equal to the minimal bounds that have been handed into it.
By combining simply three modifiers, we have been in a position to outline a measurement for our composable and middle it in its mother or father!
Downside 3
/* Copyright 2023 Google LLC.
SPDX-License-Identifier: Apache-2.0 */Picture(
painterResource(R.drawable.frag),
contentDescription = null,
Modifier
.clip(CircleShape)
.padding(10.dp)
.measurement(100.dp)
)
Right here’s the answer:
- The
clip
modifier doesn’t change the constraints. - The
padding
modifier lowers the utmost constraints. - The
measurement
modifier units all constraints to100dp
. - The
Picture
adheres to these constraints and reviews a measurement of100
by100dp
. - The
padding
modifier provides10dp
on all sizes, so it will increase the reported width and top by20dp
. - Now within the drawing section, the
clip
modifier acts on a canvas of120
by120dp
. Thus it creates a circle masks of that measurement. - The
padding
modifier then insets its content material by10dp
on all sizes, so it lowers the canvas measurement to100
by100dp
. - The
Picture
is then drawn in that canvas. You possibly can see that the picture is clipped primarily based on the unique circle of120dp
, and thus we see a non-round outcome.
Wow, that was so much! You realized about constraints, and used them to purpose about modifiers, learn how to organize them, and measurements.
Within the subsequent publish we’ll present you the way you should utilize this info to start out implementing your individual customized structure.
Bought any questions? Depart a remark beneath or use the #MADCompose hashtag on Twitter and we’ll tackle your questions in our upcoming reside Q&A for the collection on March ninth. Keep tuned!