funModifier.firstBaselineToTop(firstBaselineToTop:Dp)=layout{measurable,constraints->
// Measure the composablevalplaceable=measurable.measure(constraints)// Check the composable has a first baselinecheck(placeable[FirstBaseline]!=AlignmentLine.Unspecified)valfirstBaseline=placeable[FirstBaseline]// Height of the composable with padding - first baselinevalplaceableY=firstBaselineToTop.roundToPx()-firstBaselinevalheight=placeable.height+placeableYlayout(placeable.width,height){// Where the composable gets placedplaceable.placeRelative(0,placeableY)}}
@ComposablefunMyBasicColumn(modifier:Modifier=Modifier,content:@Composable()->Unit){Layout(modifier=modifier,content=content){measurables,constraints->
// measure and position children given constraints logic here// ...}}
@ComposablefunMyBasicColumn(modifier:Modifier=Modifier,content:@Composable()->Unit){Layout(modifier=modifier,content=content){measurables,constraints->
// Don't constrain child views further, measure them with given constraints// List of measured childrenvalplaceables=measurables.map{measurable->
// Measure each childrenmeasurable.measure(constraints)}// Set the size of the layout as big as it canlayout(constraints.maxWidth,constraints.maxHeight){// Track the y co-ord we have placed children up tovaryPosition=0// Place children in the parent layoutplaceables.forEach{placeable->
// Position item on the screenplaceable.placeRelative(x=0,y=yPosition)// Record the y co-ord placed up toyPosition+=placeable.height}}}}
@ComposablefunCallingComposable(modifier:Modifier=Modifier){MyBasicColumn(modifier.padding(8.dp)){Text("MyBasicColumn")Text("places items")Text("vertically.")Text("We've done it by hand!")}}
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-08-22 (世界標準時間)。"],[],[],null,["In Compose, UI elements are represented by the composable functions that emit a\npiece of UI when invoked, that is then added to a UI tree that gets rendered on\nthe screen. Each UI element has one parent and potentially many children. Each\nelement is also located within its parent, specified as an (x, y) position, and\na size, specified as a `width` and a `height`.\n\nParents define the constraints for their child elements. An element is asked to\ndefine its size within those constraints. Constraints restrict the minimum and\nmaximum `width` and `height` of an element. If an element has child elements, it\nmay measure each child to help determine its size. Once an element determines\nand reports its own size, it has an opportunity to define how to place its child\nelements relative to itself, as described in detail in [Creating custom\nlayouts](#create-custom).\n\nLaying out each node in the UI tree is a three step process. Each node must:\n\n1. Measure any children\n2. Decide its own size\n3. Place its children\n\n| **Note:** Compose UI does not permit multi-pass measurement. This means that a layout element may not measure any of its children more than once in order to try different measurement configurations.\n\nThe use of scopes defines *when* you can measure and place your children.\nMeasuring a layout can only be done during the measurement and layout passes,\nand a child can only be placed during the layout passes (and only after it has\nbeen measured). Due to Compose scopes such as\n[`MeasureScope`](/reference/kotlin/androidx/compose/ui/layout/MeasureScope),\nand [`PlacementScope`](/reference/kotlin/androidx/compose/ui/layout/Placeable.PlacementScope),\nthis is enforced at compile time.\n\nUse the layout modifier \n\nYou can use the `layout` modifier to modify how an element is measured and laid\nout. `Layout` is a lambda; its parameters include the element you can measure,\npassed as `measurable`, and that composable's incoming constraints, passed as\n`constraints`. A custom layout modifier can look like this:\n\n\n```kotlin\nfun Modifier.customLayoutModifier() =\n layout { measurable, constraints -\u003e\n // ...\n }https://github.com/android/snippets/blob/5673ffc60b614daf028ee936227128eb8c4f9781/compose/snippets/src/main/java/com/example/compose/snippets/layouts/CustomLayoutSnippets.kt#L54-L63\n```\n\n\u003cbr /\u003e\n\nLet's display a `Text` on the screen and control the distance from the top to\nthe baseline of the first line of text. This is exactly what the\n`paddingFromBaseline` modifier does, we're implementing it here as an example.\nTo do that, use the `layout` modifier to manually place the composable on the\nscreen. Here's the desired behavior where the `Text` top padding is set `24.dp`:\n\nHere's the code to produce that spacing:\n\n\n```kotlin\nfun Modifier.firstBaselineToTop(\n firstBaselineToTop: Dp\n) = layout { measurable, constraints -\u003e\n // Measure the composable\n val placeable = measurable.measure(constraints)\n\n // Check the composable has a first baseline\n check(placeable[FirstBaseline] != AlignmentLine.Unspecified)\n val firstBaseline = placeable[FirstBaseline]\n\n // Height of the composable with padding - first baseline\n val placeableY = firstBaselineToTop.roundToPx() - firstBaseline\n val height = placeable.height + placeableY\n layout(placeable.width, height) {\n // Where the composable gets placed\n placeable.placeRelative(0, placeableY)\n }\n}https://github.com/android/snippets/blob/5673ffc60b614daf028ee936227128eb8c4f9781/compose/snippets/src/main/java/com/example/compose/snippets/layouts/CustomLayoutSnippets.kt#L69-L86\n```\n\n\u003cbr /\u003e\n\nHere's what's going on in that code:\n\n1. In the `measurable` lambda parameter, you measure the `Text` represented by the measurable parameter by calling `measurable.measure(constraints)`.\n2. You specify the size of the composable by calling the `layout(width, height)` method, which also gives a lambda used for placing the wrapped elements. In this case, it's the height between the last baseline and added top padding.\n3. You position the wrapped elements on the screen by calling `placeable.place(x, y)`. If the wrapped elements aren't placed, they won't be visible. The `y`position corresponds to the top padding - the position of the first baseline of the text.\n\nTo verify this works as expected, use this modifier on a `Text`:\n\n\n```kotlin\n@Preview\n@Composable\nfun TextWithPaddingToBaselinePreview() {\n MyApplicationTheme {\n Text(\"Hi there!\", Modifier.firstBaselineToTop(32.dp))\n }\n}\n\n@Preview\n@Composable\nfun TextWithNormalPaddingPreview() {\n MyApplicationTheme {\n Text(\"Hi there!\", Modifier.padding(top = 32.dp))\n }\n}https://github.com/android/snippets/blob/5673ffc60b614daf028ee936227128eb8c4f9781/compose/snippets/src/main/java/com/example/compose/snippets/layouts/CustomLayoutSnippets.kt#L91-L105\n```\n\n\u003cbr /\u003e\n\nCreate custom layouts\n\nThe `layout` modifier only changes the calling composable. To measure and layout\nmultiple composables, use the [`Layout`](/reference/kotlin/androidx/compose/ui/layout/package-summary#Layout(kotlin.collections.List,androidx.compose.ui.Modifier,androidx.compose.ui.layout.MultiContentMeasurePolicy)) composable instead. This composable\nallows you to measure and lay out children manually. All higher-level layouts\nlike `Column` and `Row` are built with the `Layout` composable.\n| **Note:** In the View system, creating a custom layout required extending `ViewGroup` and implementing measure and layout functions. In Compose you simply write a function using the `Layout` composable.\n\nLet's build a very basic version of `Column`. Most custom layouts follow this\npattern:\n\n\n```kotlin\n@Composable\nfun MyBasicColumn(\n modifier: Modifier = Modifier,\n content: @Composable () -\u003e Unit\n) {\n Layout(\n modifier = modifier,\n content = content\n ) { measurables, constraints -\u003e\n // measure and position children given constraints logic here\n // ...\n }\n}https://github.com/android/snippets/blob/5673ffc60b614daf028ee936227128eb8c4f9781/compose/snippets/src/main/java/com/example/compose/snippets/layouts/CustomLayoutSnippets.kt#L110-L142\n```\n\n\u003cbr /\u003e\n\nSimilarly to the `layout` modifier, `measurables` is the list of children that\nneed to be measured and `constraints` are the constraints from the parent.\nFollowing the same logic as before, `MyBasicColumn` can be implemented like\nthis:\n\n\n```kotlin\n@Composable\nfun MyBasicColumn(\n modifier: Modifier = Modifier,\n content: @Composable () -\u003e Unit\n) {\n Layout(\n modifier = modifier,\n content = content\n ) { measurables, constraints -\u003e\n // Don't constrain child views further, measure them with given constraints\n // List of measured children\n val placeables = measurables.map { measurable -\u003e\n // Measure each children\n measurable.measure(constraints)\n }\n\n // Set the size of the layout as big as it can\n layout(constraints.maxWidth, constraints.maxHeight) {\n // Track the y co-ord we have placed children up to\n var yPosition = 0\n\n // Place children in the parent layout\n placeables.forEach { placeable -\u003e\n // Position item on the screen\n placeable.placeRelative(x = 0, y = yPosition)\n\n // Record the y co-ord placed up to\n yPosition += placeable.height\n }\n }\n }\n}https://github.com/android/snippets/blob/5673ffc60b614daf028ee936227128eb8c4f9781/compose/snippets/src/main/java/com/example/compose/snippets/layouts/CustomLayoutSnippets.kt#L148-L179\n```\n\n\u003cbr /\u003e\n\nThe child composables are constrained by the `Layout` constraints (without the\n`minHeight` constraints), and they're placed based on the `yPosition` of the\nprevious composable.\n\nHere's how that custom composable would be used:\n\n\n```kotlin\n@Composable\nfun CallingComposable(modifier: Modifier = Modifier) {\n MyBasicColumn(modifier.padding(8.dp)) {\n Text(\"MyBasicColumn\")\n Text(\"places items\")\n Text(\"vertically.\")\n Text(\"We've done it by hand!\")\n }\n}https://github.com/android/snippets/blob/5673ffc60b614daf028ee936227128eb8c4f9781/compose/snippets/src/main/java/com/example/compose/snippets/layouts/CustomLayoutSnippets.kt#L184-L192\n```\n\n\u003cbr /\u003e\n\nLayout direction\n\nChange the layout direction of a composable by changing the\n[`LocalLayoutDirection`](/reference/kotlin/androidx/compose/ui/platform/package-summary#LocalLayoutDirection()) composition local.\n\nIf you're placing composables manually on the screen, the `LayoutDirection` is\npart of the `LayoutScope` of the `layout` modifier or `Layout` composable.\n\nWhen using `layoutDirection`, place composables using [`place`](/reference/kotlin/androidx/compose/ui/layout/Placeable.PlacementScope#place(androidx.compose.ui.layout.Placeable,kotlin.Int,kotlin.Int,kotlin.Float)). Unlike the\n[`placeRelative`](/reference/kotlin/androidx/compose/ui/layout/Placeable.PlacementScope#placeRelative(androidx.compose.ui.layout.Placeable,kotlin.Int,kotlin.Int,kotlin.Float))\nmethod, `place` doesn't change based on the layout direction\n(left-to-right versus right-to-left).\n\nCustom layouts in action\n\nLearn more about layouts and modifiers in the\n[Basic layouts in Compose](/codelabs/jetpack-compose-layouts),\nand see custom layouts in action in the\n[Compose samples that create custom layouts](https://github.com/android/compose-samples/search?q=androidx.compose.ui.layout.Layout).\n\nLearn more\n\nTo learn more about custom layouts in Compose, consult the following additional\nresources.\n\nVideos\n\n- [A deep dive into Jetpack Compose Layouts](https://www.youtube.com/watch?v=zMKMwh9gZuI)\n\nRecommended for you\n\n- Note: link text is displayed when JavaScript is off\n- [Intrinsic measurements in Compose layouts](/develop/ui/compose/layouts/intrinsic-measurements)\n- [Graphics in Compose](/develop/ui/compose/graphics/draw/overview)\n- [Compose modifiers](/develop/ui/compose/modifiers)"]]