Refactor showSelectItemWithIcon layout
This commit is contained in:
1 parent
174e899ead
commit
8c0e217117
2 files changed
+66
-16
No files matched your search
@@ -0,0 +1,46 @@
|
||||
package com.hippo.ehviewer.ui.tools
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.sin
|
||||
|
||||
private const val FullCircle: Float = (PI * 2).toFloat()
|
||||
private const val QuarterCircle = PI / 2
|
||||
|
||||
@Composable
|
||||
fun CircularLayout(
|
||||
modifier: Modifier = Modifier,
|
||||
radius: Dp,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Layout(
|
||||
modifier = modifier,
|
||||
content = content,
|
||||
) { measurables, constraints ->
|
||||
val radiusPx = radius.toPx()
|
||||
val itemConstraints = constraints.copy(minWidth = 0, minHeight = 0)
|
||||
val placeables = measurables.map { measurable -> measurable.measure(itemConstraints) }
|
||||
val theta = FullCircle / (placeables.count())
|
||||
|
||||
layout(
|
||||
width = constraints.minWidth,
|
||||
height = constraints.minHeight,
|
||||
) {
|
||||
placeables.forEachIndexed { i, it ->
|
||||
val centerOffsetX = constraints.maxWidth / 2 - it.width / 2
|
||||
val centerOffsetY = constraints.maxHeight / 2 - it.height / 2
|
||||
val offsetX = radiusPx * cos(theta * i - QuarterCircle) + centerOffsetX
|
||||
val offsetY = radiusPx * sin(theta * i - QuarterCircle) + centerOffsetY
|
||||
it.place(
|
||||
x = offsetX.roundToInt(),
|
||||
y = offsetY.roundToInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -25,6 +27,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -115,7 +118,7 @@ class DialogState {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun <R> showNoButton(block: @Composable DismissDialogScope<R>.() -> Unit): R {
|
||||
private suspend fun <R> showNoButton(respectDefaultWidth: Boolean = true, block: @Composable DismissDialogScope<R>.() -> Unit): R {
|
||||
return suspendCancellableCoroutine { cont ->
|
||||
cont.invokeOnCancellation { dismiss() }
|
||||
content = {
|
||||
@@ -132,7 +135,7 @@ class DialogState {
|
||||
},
|
||||
content = {
|
||||
Surface(
|
||||
modifier = Modifier.width(280.dp),
|
||||
modifier = with(Modifier) { if (!respectDefaultWidth) defaultMinSize(280.dp) else width(280.dp) },
|
||||
shape = AlertDialogDefaults.shape,
|
||||
color = AlertDialogDefaults.containerColor,
|
||||
tonalElevation = AlertDialogDefaults.TonalElevation,
|
||||
@@ -184,21 +187,22 @@ class DialogState {
|
||||
suspend fun showSelectItemWithIcon(
|
||||
vararg items: Pair<ImageVector, String>,
|
||||
@StringRes title: Int,
|
||||
): Int = showNoButton {
|
||||
LazyColumn {
|
||||
stickyHeader {
|
||||
Text(text = stringResource(id = title), modifier = Modifier.padding(horizontal = 16.dp).padding(top = 16.dp), style = MaterialTheme.typography.titleMedium)
|
||||
}
|
||||
itemsIndexed(items) { index, (icon, text) ->
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(text = text, style = MaterialTheme.typography.titleMedium)
|
||||
},
|
||||
modifier = Modifier.clickable { dismissWith(index) },
|
||||
leadingContent = {
|
||||
): Int = showNoButton(false) {
|
||||
Column {
|
||||
Text(text = stringResource(id = title), modifier = Modifier.padding(horizontal = 16.dp).padding(top = 16.dp), style = MaterialTheme.typography.titleMedium)
|
||||
CircularLayout(
|
||||
radius = 112.dp,
|
||||
modifier = Modifier.fillMaxWidth().aspectRatio(1F),
|
||||
) {
|
||||
items.forEachIndexed { index, (icon, text) ->
|
||||
Column(
|
||||
modifier = Modifier.clickable { dismissWith(index) },
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(imageVector = icon, contentDescription = null, tint = AlertDialogDefaults.iconContentColor)
|
||||
},
|
||||
)
|
||||
Text(text = text, style = MaterialTheme.typography.bodySmall)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user