@@ -14,8 +14,10 @@ import androidx.compose.foundation.layout.ime
14
14
import androidx.compose.foundation.layout.isImeVisible
15
15
import androidx.compose.foundation.layout.systemBars
16
16
import androidx.compose.foundation.layout.union
17
+ import androidx.compose.foundation.layout.wrapContentSize
17
18
import androidx.compose.runtime.Composable
18
19
import androidx.compose.runtime.remember
20
+ import androidx.compose.ui.Alignment
19
21
import androidx.compose.ui.Modifier
20
22
import androidx.compose.ui.graphics.Brush
21
23
import androidx.compose.ui.graphics.Color
@@ -91,31 +93,27 @@ private fun ScaffoldLayout(
91
93
val looseConstraints = constraints.copy(minWidth = 0 , minHeight = 0 )
92
94
93
95
val topBarPlaceables = subcompose(SlotTopAppBar , topBar).map { it.measure(looseConstraints) }
94
- val actionPlaceables = subcompose(SlotAction , action).map { it.measure(looseConstraints) }
95
- val toastPlaceables = subcompose(SlotToast , toast).map { it.measure(looseConstraints) }
96
+ val topBarHeight = topBarPlaceables.maxOfOrNull { it.height } ? : 0
96
97
98
+ val maxActionHeight = layoutHeight - topBarHeight
99
+ val actionConstraints = looseConstraints.copy(maxHeight = maxActionHeight)
100
+ val actionPlaceables = subcompose(SlotAction , action).map { it.measure(actionConstraints) }
97
101
val actionHeight = actionPlaceables.maxOfOrNull { it.height } ? : 0
98
102
val actionFadeHeight = actionPlaceables.firstOrNull()?.get(ActionFadeLine )?.let { value ->
99
103
if (value == AlignmentLine .Unspecified ) 0 else value
100
104
} ? : 0
101
105
102
106
val contentInsets = contentWindowInsets.asPaddingValues(this )
103
- val contentTop = topBarPlaceables.maxOfOrNull { it.height } ? : 0
104
- val contentBottom = if (actionHeight > 0 ) {
107
+ val occupiedBottomSize = if (actionHeight > 0 ) {
105
108
(actionHeight - actionFadeHeight).coerceAtLeast(0 )
106
109
} else {
107
- if (imeOpened) {
108
- contentInsets.calculateBottomPadding().roundToPx()
109
- } else {
110
- 0
111
- }
110
+ if (imeOpened) contentInsets.calculateBottomPadding().roundToPx() else 0
112
111
}
113
112
val contentConstraints = looseConstraints.copy(
114
- maxHeight = layoutHeight - contentTop - contentBottom ,
113
+ maxHeight = layoutHeight - topBarHeight - occupiedBottomSize ,
115
114
)
116
-
117
115
val innerPadding = PaddingValues (
118
- top = if (contentTop > 0 ) {
116
+ top = if (topBarHeight > 0 ) {
119
117
0 .dp
120
118
} else {
121
119
contentInsets.calculateTopPadding()
@@ -136,11 +134,13 @@ private fun ScaffoldLayout(
136
134
content(innerPadding)
137
135
}.map { it.measure(contentConstraints) }
138
136
137
+ val toastPlaceables = subcompose(SlotToast , toast).map { it.measure(looseConstraints) }
138
+
139
139
layout(layoutWidth, layoutHeight) {
140
- contentPlaceables.forEach { it.placeRelative(0 , contentTop ) }
140
+ contentPlaceables.forEach { it.placeRelative(0 , topBarHeight ) }
141
141
topBarPlaceables.forEach { it.placeRelative(0 , 0 ) }
142
142
actionPlaceables.forEach { it.placeRelative(0 , layoutHeight - actionHeight) }
143
- toastPlaceables.forEach { it.placeRelative(0 , contentTop ) }
143
+ toastPlaceables.forEach { it.placeRelative(0 , topBarHeight ) }
144
144
}
145
145
}
146
146
}
@@ -174,15 +174,17 @@ public fun ScaffoldAction(
174
174
},
175
175
) { measurables, constraints ->
176
176
val padding = 16 .dp.roundToPx()
177
+ val top = fadeHeight.roundToPx()
177
178
val action = measurables.first().measure(
178
- constraints.offset(horizontal = padding * - 2 ),
179
+ constraints
180
+ .offset(horizontal = padding * - 2 )
181
+ .copy(maxHeight = (constraints.maxHeight - padding - top).coerceAtLeast(0 )),
179
182
)
180
183
181
184
if (action.height == 0 ) {
182
185
return @Layout layout(0 , 0 ) {}
183
186
}
184
187
185
- val top = fadeHeight.roundToPx()
186
188
val width = constraints.maxWidth
187
189
val height = top + action.height + padding + inset.calculateBottomPadding().roundToPx()
188
190
@@ -220,3 +222,39 @@ internal fun ScaffoldPreview() {
220
222
}
221
223
}
222
224
}
225
+
226
+ @OrbitPreviews
227
+ @Composable
228
+ internal fun ScaffoldPreviewWithFullScreenAction () {
229
+ Preview {
230
+ Scaffold (
231
+ topBar = {
232
+ TopAppBar (title = { Text (text = " Title" ) })
233
+ },
234
+ action = {
235
+ Box (
236
+ modifier = Modifier
237
+ .fillMaxSize()
238
+ .background(OrbitTheme .colors.surface.normal),
239
+ ) {
240
+ Text (
241
+ text = " Custom full screen action" ,
242
+ modifier = Modifier
243
+ .fillMaxSize()
244
+ .wrapContentSize(),
245
+ )
246
+ ButtonPrimary (
247
+ onClick = {},
248
+ modifier = Modifier
249
+ .fillMaxWidth()
250
+ .align(Alignment .BottomCenter ),
251
+ ) {
252
+ Text (" Custom full screen action" )
253
+ }
254
+ }
255
+ },
256
+ ) {
257
+ CustomPlaceholder (Modifier .fillMaxSize())
258
+ }
259
+ }
260
+ }
0 commit comments