refactor: use properties to share data in DropdownList

This commit is contained in:
2023-11-18 04:06:12 +08:00
parent e7bff01dc8
commit 604ec4bec0
4 changed files with 94 additions and 46 deletions

View File

@@ -38,21 +38,36 @@ import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.node.Ref import androidx.compose.ui.node.Ref
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.semantics.Role
import com.highcapable.flexiui.interaction.rippleClickable
import kotlin.math.max import kotlin.math.max
@Composable @Composable
internal actual fun DropdownListBox( internal actual fun DropdownListBox(
expanded: Boolean,
onExpandedChange: (Boolean) -> Unit,
modifier: Modifier, modifier: Modifier,
properties: DropdownListProperties,
menuHeightPx: (Int) -> Unit, menuHeightPx: (Int) -> Unit,
content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit
) { ) {
val view = LocalView.current val view = LocalView.current
val coordinates = remember { Ref<LayoutCoordinates>() } val coordinates = remember { Ref<LayoutCoordinates>() }
BoxWithConstraints( BoxWithConstraints(
modifier = modifier.onGloballyPositioned { modifier = Modifier.dropdownList(
properties = properties,
modifier = modifier.rippleClickable(
enabled = properties.enabled,
role = Role.DropdownList,
interactionSource = properties.interactionSource
) {
properties.focusRequester.requestFocus()
onExpandedChange(!expanded)
}.onGloballyPositioned {
coordinates.value = it coordinates.value = it
updateHeight(view.rootView, coordinates.value) { newHeight -> menuHeightPx(newHeight) } updateHeight(view.rootView, coordinates.value) { newHeight -> menuHeightPx(newHeight) }
}, }
),
content = content content = content
) )
DisposableEffect(view) { DisposableEffect(view) {

View File

@@ -183,21 +183,16 @@ fun DropdownList(
else -> style.borderInactive else -> style.borderInactive
}.copy(animatedBorderWidth, SolidColor(animatedBorderColor)) }.copy(animatedBorderWidth, SolidColor(animatedBorderColor))
DropdownListBox( DropdownListBox(
modifier = modifier.dropdownList( expanded = expanded,
onExpandedChange = onExpandedChange,
modifier = modifier,
properties = DropdownListProperties(
colors = colors, colors = colors,
style = style, style = style,
border = border, border = border,
enabled = enabled, enabled = enabled,
focusRequester = focusRequester, focusRequester = focusRequester,
interactionSource = interactionSource,
modifier = modifier.rippleClickable(
enabled = enabled,
role = Role.DropdownList,
interactionSource = interactionSource interactionSource = interactionSource
) {
focusRequester.requestFocus()
onExpandedChange(!expanded)
}
), ),
menuHeightPx = { menuHeightPx = it } menuHeightPx = { menuHeightPx = it }
) { ) {
@@ -366,32 +361,40 @@ private fun DropdownMenuContent(
@Composable @Composable
internal expect fun DropdownListBox( internal expect fun DropdownListBox(
expanded: Boolean,
onExpandedChange: (Boolean) -> Unit,
modifier: Modifier, modifier: Modifier,
properties: DropdownListProperties,
menuHeightPx: (Int) -> Unit, menuHeightPx: (Int) -> Unit,
content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit
) )
private fun Modifier.dropdownList( internal fun Modifier.dropdownList(
colors: DropdownListColors, properties: DropdownListProperties,
style: DropdownListStyle,
border: BorderStroke,
enabled: Boolean,
focusRequester: FocusRequester,
interactionSource: MutableInteractionSource,
modifier: Modifier modifier: Modifier
) = status(enabled) ) = status(properties.enabled)
.focusRequester(focusRequester) .focusRequester(properties.focusRequester)
.focusable(enabled, interactionSource) .focusable(properties.enabled, properties.interactionSource)
.hoverable(interactionSource, enabled) .hoverable(properties.interactionSource, properties.enabled)
.clip(style.shape) .clip(properties.style.shape)
.background(colors.backgroundColor, style.shape) .background(properties.colors.backgroundColor, properties.style.shape)
.borderOrNot(border, style.shape) .borderOrNot(properties.border, properties.style.shape)
.then(modifier) .then(modifier)
.padding( .padding(
top = style.topPadding.orElse() ?: style.padding, top = properties.style.topPadding.orElse() ?: properties.style.padding,
start = style.startPadding.orElse() ?: style.padding, start = properties.style.startPadding.orElse() ?: properties.style.padding,
bottom = style.bottomPadding.orElse() ?: style.padding, bottom = properties.style.bottomPadding.orElse() ?: properties.style.padding,
end = style.endPadding.orElse() ?: style.padding end = properties.style.endPadding.orElse() ?: properties.style.padding
)
@Immutable
internal data class DropdownListProperties(
val colors: DropdownListColors,
val style: DropdownListStyle,
val border: BorderStroke,
val enabled: Boolean,
val focusRequester: FocusRequester,
val interactionSource: MutableInteractionSource
) )
private fun calculateTransformOrigin(parentBounds: IntRect, menuBounds: IntRect): TransformOrigin { private fun calculateTransformOrigin(parentBounds: IntRect, menuBounds: IntRect): TransformOrigin {

View File

@@ -31,24 +31,39 @@ import androidx.compose.ui.UiComposable
import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.platform.LocalWindowInfo
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.toIntRect import androidx.compose.ui.unit.toIntRect
import com.highcapable.flexiui.interaction.rippleClickable
import kotlin.math.max import kotlin.math.max
@Composable @Composable
internal actual fun DropdownListBox( internal actual fun DropdownListBox(
expanded: Boolean,
onExpandedChange: (Boolean) -> Unit,
modifier: Modifier, modifier: Modifier,
properties: DropdownListProperties,
menuHeightPx: (Int) -> Unit, menuHeightPx: (Int) -> Unit,
content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit
) { ) {
val windowInfo = LocalWindowInfo.current val windowInfo = LocalWindowInfo.current
BoxWithConstraints( BoxWithConstraints(
modifier = modifier.onGloballyPositioned { modifier = Modifier.dropdownList(
properties = properties,
modifier = modifier.rippleClickable(
enabled = properties.enabled,
role = Role.DropdownList,
interactionSource = properties.interactionSource
) {
properties.focusRequester.requestFocus()
onExpandedChange(!expanded)
}.onGloballyPositioned {
val boundsInWindow = it.boundsInWindow() val boundsInWindow = it.boundsInWindow()
val visibleWindowBounds = windowInfo.containerSize.toIntRect() val visibleWindowBounds = windowInfo.containerSize.toIntRect()
val heightAbove = boundsInWindow.top - visibleWindowBounds.top val heightAbove = boundsInWindow.top - visibleWindowBounds.top
val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom
menuHeightPx(max(heightAbove, heightBelow).toInt()) menuHeightPx(max(heightAbove, heightBelow).toInt())
}, }
),
content = content content = content
) )
} }

View File

@@ -31,24 +31,39 @@ import androidx.compose.ui.UiComposable
import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.platform.LocalWindowInfo
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.toIntRect import androidx.compose.ui.unit.toIntRect
import com.highcapable.flexiui.interaction.rippleClickable
import kotlin.math.max import kotlin.math.max
@Composable @Composable
internal actual fun DropdownListBox( internal actual fun DropdownListBox(
expanded: Boolean,
onExpandedChange: (Boolean) -> Unit,
modifier: Modifier, modifier: Modifier,
properties: DropdownListProperties,
menuHeightPx: (Int) -> Unit, menuHeightPx: (Int) -> Unit,
content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit
) { ) {
val windowInfo = LocalWindowInfo.current val windowInfo = LocalWindowInfo.current
BoxWithConstraints( BoxWithConstraints(
modifier = modifier.onGloballyPositioned { modifier = Modifier.dropdownList(
properties = properties,
modifier = modifier.rippleClickable(
enabled = properties.enabled,
role = Role.DropdownList,
interactionSource = properties.interactionSource
) {
properties.focusRequester.requestFocus()
onExpandedChange(!expanded)
}.onGloballyPositioned {
val boundsInWindow = it.boundsInWindow() val boundsInWindow = it.boundsInWindow()
val visibleWindowBounds = windowInfo.containerSize.toIntRect() val visibleWindowBounds = windowInfo.containerSize.toIntRect()
val heightAbove = boundsInWindow.top - visibleWindowBounds.top val heightAbove = boundsInWindow.top - visibleWindowBounds.top
val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom
menuHeightPx(max(heightAbove, heightBelow).toInt()) menuHeightPx(max(heightAbove, heightBelow).toInt())
}, }
),
content = content content = content
) )
} }