Remove unintended inner card borders from search results
This commit is contained in:
parent
7ddd7a2309
commit
aefc410778
@ -1,11 +1,26 @@
|
||||
package de.mm20.launcher2.ui.component
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.shape.CornerSize
|
||||
import androidx.compose.material3.LocalAbsoluteTonalElevation
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.drawOutline
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.graphics.drawscope.withTransform
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||
@ -29,4 +44,149 @@ fun LauncherCard(
|
||||
shadowElevation = if (backgroundOpacity == 1f) elevation else 0.dp,
|
||||
tonalElevation = elevation
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PartialLauncherCard(
|
||||
modifier: Modifier = Modifier,
|
||||
isTop: Boolean = false,
|
||||
isBottom: Boolean = false,
|
||||
elevation: Dp = 2.dp,
|
||||
backgroundOpacity: Float = LocalCardStyle.current.opacity,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
|
||||
if (isTop && isBottom) {
|
||||
LauncherCard(modifier = modifier, content = content)
|
||||
} else if (!isTop && !isBottom) {
|
||||
CardMiddlePiece(modifier = modifier, elevation = elevation, content = content)
|
||||
} else {
|
||||
CardEndPiece(
|
||||
modifier = modifier,
|
||||
isTop = isTop,
|
||||
isBottom = isBottom,
|
||||
elevation = elevation,
|
||||
backgroundOpacity = backgroundOpacity,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CardMiddlePiece(
|
||||
modifier: Modifier,
|
||||
elevation: Dp,
|
||||
backgroundOpacity: Float = LocalCardStyle.current.opacity,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val borderWidth = LocalCardStyle.current.borderWidth.dp
|
||||
val borderColor = MaterialTheme.colorScheme.surface
|
||||
|
||||
val absoluteElevation = LocalAbsoluteTonalElevation.current + elevation
|
||||
Box(
|
||||
modifier = modifier
|
||||
.shadow(elevation, RectangleShape, true)
|
||||
.background(
|
||||
if (backgroundOpacity == 1f) {
|
||||
MaterialTheme.colorScheme.surfaceColorAtElevation(absoluteElevation)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surface.copy(
|
||||
alpha = backgroundOpacity.coerceIn(
|
||||
0f,
|
||||
1f
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.drawBehind {
|
||||
if (borderWidth == 0.dp) return@drawBehind
|
||||
val border = borderWidth.toPx()
|
||||
drawRect(
|
||||
color = borderColor,
|
||||
topLeft = Offset.Zero,
|
||||
size = size.copy(width = border)
|
||||
)
|
||||
drawRect(
|
||||
color = borderColor,
|
||||
topLeft = Offset(size.width - border, 0f),
|
||||
size = size.copy(width = border)
|
||||
)
|
||||
},
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides MaterialTheme.colorScheme.onSurface,
|
||||
LocalAbsoluteTonalElevation provides absoluteElevation,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CardEndPiece(
|
||||
modifier: Modifier = Modifier,
|
||||
isTop: Boolean,
|
||||
isBottom: Boolean,
|
||||
elevation: Dp,
|
||||
backgroundOpacity: Float,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val shape = when {
|
||||
isTop -> MaterialTheme.shapes.medium.copy(
|
||||
bottomEnd = CornerSize(0),
|
||||
bottomStart = CornerSize(0),
|
||||
)
|
||||
isBottom -> MaterialTheme.shapes.medium.copy(
|
||||
topEnd = CornerSize(0),
|
||||
topStart = CornerSize(0),
|
||||
)
|
||||
else -> RectangleShape
|
||||
}
|
||||
|
||||
val borderWidth = LocalCardStyle.current.borderWidth.dp
|
||||
val borderColor = MaterialTheme.colorScheme.surface
|
||||
|
||||
val absoluteElevation = LocalAbsoluteTonalElevation.current + elevation
|
||||
Box(
|
||||
modifier = modifier
|
||||
.shadow(elevation, shape, true)
|
||||
.background(
|
||||
if (backgroundOpacity == 1f) {
|
||||
MaterialTheme.colorScheme.surfaceColorAtElevation(absoluteElevation)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surface.copy(
|
||||
alpha = backgroundOpacity.coerceIn(
|
||||
0f,
|
||||
1f
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.drawWithCache {
|
||||
val border = borderWidth.toPx()
|
||||
val outline = shape.createOutline(
|
||||
size.copy(height = size.height + border),
|
||||
layoutDirection,
|
||||
Density(density, fontScale)
|
||||
)
|
||||
onDrawBehind {
|
||||
withTransform({
|
||||
translate(0f, if (isBottom) -border else 0f)
|
||||
}) {
|
||||
drawOutline(
|
||||
outline,
|
||||
borderColor,
|
||||
style = Stroke(width = border * 2)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides MaterialTheme.colorScheme.onSurface,
|
||||
LocalAbsoluteTonalElevation provides absoluteElevation,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.component.LauncherCard
|
||||
import de.mm20.launcher2.ui.component.PartialLauncherCard
|
||||
import de.mm20.launcher2.ui.launcher.search.calculator.CalculatorItem
|
||||
import de.mm20.launcher2.ui.launcher.search.common.grid.GridItem
|
||||
import de.mm20.launcher2.ui.launcher.search.common.list.ListItem
|
||||
@ -127,25 +128,15 @@ fun GridRow(
|
||||
modifier = modifier
|
||||
.clipToBounds()
|
||||
) {
|
||||
LauncherCard(
|
||||
PartialLauncherCard(
|
||||
modifier = Modifier.padding(
|
||||
start = 8.dp,
|
||||
end = 8.dp,
|
||||
top = if (isFirst) 4.dp else 0.dp,
|
||||
bottom = if (isLast) 4.dp else 0.dp,
|
||||
),
|
||||
shape = when {
|
||||
isFirst && isLast -> MaterialTheme.shapes.medium
|
||||
isFirst -> MaterialTheme.shapes.medium.copy(
|
||||
bottomEnd = CornerSize(0),
|
||||
bottomStart = CornerSize(0),
|
||||
)
|
||||
isLast -> MaterialTheme.shapes.medium.copy(
|
||||
topEnd = CornerSize(0),
|
||||
topStart = CornerSize(0),
|
||||
)
|
||||
else -> RectangleShape
|
||||
}
|
||||
isTop = isFirst,
|
||||
isBottom = isLast,
|
||||
) {
|
||||
Row {
|
||||
for (item in items) {
|
||||
@ -190,25 +181,15 @@ fun ListRow(
|
||||
modifier = modifier
|
||||
.clipToBounds()
|
||||
) {
|
||||
LauncherCard(
|
||||
PartialLauncherCard(
|
||||
modifier = Modifier.padding(
|
||||
start = 8.dp,
|
||||
end = 8.dp,
|
||||
top = if (isFirst) 4.dp else 0.dp,
|
||||
bottom = if (isLast) 4.dp else 0.dp,
|
||||
),
|
||||
shape = when {
|
||||
isFirst && isLast -> MaterialTheme.shapes.medium
|
||||
isFirst -> MaterialTheme.shapes.medium.copy(
|
||||
bottomEnd = CornerSize(0),
|
||||
bottomStart = CornerSize(0),
|
||||
)
|
||||
isLast -> MaterialTheme.shapes.medium.copy(
|
||||
topEnd = CornerSize(0),
|
||||
topStart = CornerSize(0),
|
||||
)
|
||||
else -> RectangleShape
|
||||
}
|
||||
isTop = isFirst,
|
||||
isBottom = isLast,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.padding(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user