@@ -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,28 @@ 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 maxActionRatio = 0.8f
99
+ val maxActionHeight = (layoutHeight - topBarHeight) * maxActionRatio
100
+ val actionConstraints = looseConstraints.copy(maxHeight = maxActionHeight.toInt())
101
+ val actionPlaceables = subcompose(SlotAction , action).map { it.measure(actionConstraints) }
97
102
val actionHeight = actionPlaceables.maxOfOrNull { it.height } ? : 0
98
103
val actionFadeHeight = actionPlaceables.firstOrNull()?.get(ActionFadeLine )?.let { value ->
99
104
if (value == AlignmentLine .Unspecified ) 0 else value
100
105
} ? : 0
101
106
102
107
val contentInsets = contentWindowInsets.asPaddingValues(this )
103
- val contentTop = topBarPlaceables.maxOfOrNull { it.height } ? : 0
104
108
val contentBottom = if (actionHeight > 0 ) {
105
- (actionHeight - actionFadeHeight).coerceAtLeast( 0 )
109
+ (actionHeight - actionFadeHeight)
106
110
} else {
107
- if (imeOpened) {
108
- contentInsets.calculateBottomPadding().roundToPx()
109
- } else {
110
- 0
111
- }
111
+ if (imeOpened) contentInsets.calculateBottomPadding().roundToPx() else 0
112
112
}
113
113
val contentConstraints = looseConstraints.copy(
114
- maxHeight = layoutHeight - contentTop - contentBottom,
114
+ maxHeight = layoutHeight - topBarHeight - contentBottom,
115
115
)
116
-
117
116
val innerPadding = PaddingValues (
118
- top = if (contentTop > 0 ) {
117
+ top = if (topBarHeight > 0 ) {
119
118
0 .dp
120
119
} else {
121
120
contentInsets.calculateTopPadding()
@@ -136,11 +135,13 @@ private fun ScaffoldLayout(
136
135
content(innerPadding)
137
136
}.map { it.measure(contentConstraints) }
138
137
138
+ val toastPlaceables = subcompose(SlotToast , toast).map { it.measure(looseConstraints) }
139
+
139
140
layout(layoutWidth, layoutHeight) {
140
- contentPlaceables.forEach { it.placeRelative(0 , contentTop ) }
141
+ contentPlaceables.forEach { it.placeRelative(0 , topBarHeight ) }
141
142
topBarPlaceables.forEach { it.placeRelative(0 , 0 ) }
142
143
actionPlaceables.forEach { it.placeRelative(0 , layoutHeight - actionHeight) }
143
- toastPlaceables.forEach { it.placeRelative(0 , contentTop ) }
144
+ toastPlaceables.forEach { it.placeRelative(0 , topBarHeight ) }
144
145
}
145
146
}
146
147
}
@@ -174,15 +175,19 @@ public fun ScaffoldAction(
174
175
},
175
176
) { measurables, constraints ->
176
177
val padding = 16 .dp.roundToPx()
178
+ val top = fadeHeight.roundToPx()
177
179
val action = measurables.first().measure(
178
- constraints.offset(horizontal = padding * - 2 ),
180
+ constraints
181
+ .offset(
182
+ horizontal = padding * - 2 ,
183
+ vertical = - (padding + top),
184
+ ),
179
185
)
180
186
181
187
if (action.height == 0 ) {
182
188
return @Layout layout(0 , 0 ) {}
183
189
}
184
190
185
- val top = fadeHeight.roundToPx()
186
191
val width = constraints.maxWidth
187
192
val height = top + action.height + padding + inset.calculateBottomPadding().roundToPx()
188
193
@@ -220,3 +225,39 @@ internal fun ScaffoldPreview() {
220
225
}
221
226
}
222
227
}
228
+
229
+ @OrbitPreviews
230
+ @Composable
231
+ internal fun ScaffoldWithFullScreenActionPreview () {
232
+ Preview {
233
+ Scaffold (
234
+ topBar = {
235
+ TopAppBar (title = { Text (text = " Title" ) })
236
+ },
237
+ action = {
238
+ Box (
239
+ modifier = Modifier
240
+ .fillMaxSize()
241
+ .background(OrbitTheme .colors.surface.normal),
242
+ ) {
243
+ Text (
244
+ text = " Custom full screen action" ,
245
+ modifier = Modifier
246
+ .fillMaxSize()
247
+ .wrapContentSize(),
248
+ )
249
+ ButtonPrimary (
250
+ onClick = {},
251
+ modifier = Modifier
252
+ .fillMaxWidth()
253
+ .align(Alignment .BottomCenter ),
254
+ ) {
255
+ Text (" Custom full screen action" )
256
+ }
257
+ }
258
+ },
259
+ ) {
260
+ CustomPlaceholder (Modifier .fillMaxSize())
261
+ }
262
+ }
263
+ }
0 commit comments