refactor: re-measure child components use specify padding in Scaffold

This commit is contained in:
2024-01-10 13:57:48 +08:00
parent 0c45ec726e
commit c8e6393307

View File

@@ -26,13 +26,13 @@ package com.highcapable.flexiui.component
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.SubcomposeLayout import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.highcapable.betterandroid.compose.extension.ui.ComponentPadding import com.highcapable.betterandroid.compose.extension.ui.ComponentPadding
@@ -88,22 +88,20 @@ private fun ScaffoldLayout(
content: @Composable (innerPadding: ComponentPadding) -> Unit content: @Composable (innerPadding: ComponentPadding) -> Unit
) { ) {
val density = LocalDensity.current val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current SubcomposeLayout(modifier = Modifier.windowInsetsPadding(contentWindowInsets)) { baseConstraints ->
val leftInsets = with(density) { contentWindowInsets.getLeft(density, layoutDirection).toDp() }
val topInsets = with(density) { contentWindowInsets.getTop(density).toDp() }
val rightInsets = with(density) { contentWindowInsets.getRight(density, layoutDirection).toDp() }
val bottomInsets = with(density) { contentWindowInsets.getBottom(density).toDp() }
val insetsPadding = padding.copy(
start = padding.start + leftInsets,
// Top insets padding is override by [appBar].
top = topInsets,
end = padding.end + rightInsets,
bottom = padding.bottom + bottomInsets
)
SubcomposeLayout(modifier = Modifier.padding(insetsPadding)) { constraints ->
var currentY = 0 var currentY = 0
var navigationBarHeight = 0 var navigationBarHeight = 0
val appBarPlaceables = subcompose(ScaffoldSlots.AppBar, appBar).map { it.measure(constraints) } var appBarPlaceables = subcompose(Unit, appBar).map { it.measure(baseConstraints) }
// Top insets padding is override by [appBar].
val topPadding = with(density) { if (appBarPlaceables.isNotEmpty()) 0 else padding.top.roundToPx() }
val horizontalPadding = with(density) { padding.horizontal.roundToPx() }
val bottomPadding = with(density) { padding.bottom.roundToPx() }
val constraints = baseConstraints.copy(
maxHeight = baseConstraints.maxHeight - topPadding - bottomPadding,
maxWidth = baseConstraints.maxWidth - horizontalPadding
)
// Re-measure [appBar] with new constraints.
appBarPlaceables = subcompose(ScaffoldSlots.AppBar, appBar).map { it.measure(constraints) }
val tabPlaceables = subcompose(ScaffoldSlots.Tab, tab).map { it.measure(constraints) } val tabPlaceables = subcompose(ScaffoldSlots.Tab, tab).map { it.measure(constraints) }
val navigationBarPlaceables = subcompose(ScaffoldSlots.NavigationBar, navigationBar).map { it.measure(constraints) } val navigationBarPlaceables = subcompose(ScaffoldSlots.NavigationBar, navigationBar).map { it.measure(constraints) }
// Inner content no need start and end padding. // Inner content no need start and end padding.
@@ -124,23 +122,24 @@ private fun ScaffoldLayout(
) )
val contentPlaceables = subcompose(ScaffoldSlots.Content) { content(innerPadding) }.map { it.measure(contentConstraints) } val contentPlaceables = subcompose(ScaffoldSlots.Content) { content(innerPadding) }.map { it.measure(contentConstraints) }
layout(constraints.maxWidth, constraints.maxHeight) { layout(constraints.maxWidth, constraints.maxHeight) {
val placementX = horizontalPadding / 2
var placementY = 0 var placementY = 0
appBarPlaceables.forEach { appBarPlaceables.forEach {
it.placeRelative(0, placementY) it.placeRelative(placementX, placementY)
placementY += it.height placementY += it.height
} }
tabPlaceables.forEach { tabPlaceables.forEach {
it.placeRelative(0, placementY) it.placeRelative(placementX, placementY)
placementY += it.height placementY += it.height
} }
contentPlaceables.forEach { contentPlaceables.forEach {
it.placeRelative(0, placementY) it.placeRelative(placementX, placementY)
placementY += it.height placementY += it.height
} }
var navigationBarY = constraints.maxHeight var navigationBarY = constraints.maxHeight
navigationBarPlaceables.forEach { navigationBarPlaceables.forEach {
navigationBarY -= it.height navigationBarY -= it.height
it.placeRelative(0, navigationBarY) it.placeRelative(placementX, navigationBarY)
} }
} }
} }