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
|
package de.mm20.launcher2.ui.component
|
||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
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.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.ui.Modifier
|
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.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 androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||||
@ -29,4 +44,149 @@ fun LauncherCard(
|
|||||||
shadowElevation = if (backgroundOpacity == 1f) elevation else 0.dp,
|
shadowElevation = if (backgroundOpacity == 1f) elevation else 0.dp,
|
||||||
tonalElevation = elevation
|
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 androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.search.data.Searchable
|
import de.mm20.launcher2.search.data.Searchable
|
||||||
import de.mm20.launcher2.ui.component.LauncherCard
|
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.calculator.CalculatorItem
|
||||||
import de.mm20.launcher2.ui.launcher.search.common.grid.GridItem
|
import de.mm20.launcher2.ui.launcher.search.common.grid.GridItem
|
||||||
import de.mm20.launcher2.ui.launcher.search.common.list.ListItem
|
import de.mm20.launcher2.ui.launcher.search.common.list.ListItem
|
||||||
@ -127,25 +128,15 @@ fun GridRow(
|
|||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clipToBounds()
|
.clipToBounds()
|
||||||
) {
|
) {
|
||||||
LauncherCard(
|
PartialLauncherCard(
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
start = 8.dp,
|
start = 8.dp,
|
||||||
end = 8.dp,
|
end = 8.dp,
|
||||||
top = if (isFirst) 4.dp else 0.dp,
|
top = if (isFirst) 4.dp else 0.dp,
|
||||||
bottom = if (isLast) 4.dp else 0.dp,
|
bottom = if (isLast) 4.dp else 0.dp,
|
||||||
),
|
),
|
||||||
shape = when {
|
isTop = isFirst,
|
||||||
isFirst && isLast -> MaterialTheme.shapes.medium
|
isBottom = isLast,
|
||||||
isFirst -> MaterialTheme.shapes.medium.copy(
|
|
||||||
bottomEnd = CornerSize(0),
|
|
||||||
bottomStart = CornerSize(0),
|
|
||||||
)
|
|
||||||
isLast -> MaterialTheme.shapes.medium.copy(
|
|
||||||
topEnd = CornerSize(0),
|
|
||||||
topStart = CornerSize(0),
|
|
||||||
)
|
|
||||||
else -> RectangleShape
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Row {
|
Row {
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
@ -190,25 +181,15 @@ fun ListRow(
|
|||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clipToBounds()
|
.clipToBounds()
|
||||||
) {
|
) {
|
||||||
LauncherCard(
|
PartialLauncherCard(
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
start = 8.dp,
|
start = 8.dp,
|
||||||
end = 8.dp,
|
end = 8.dp,
|
||||||
top = if (isFirst) 4.dp else 0.dp,
|
top = if (isFirst) 4.dp else 0.dp,
|
||||||
bottom = if (isLast) 4.dp else 0.dp,
|
bottom = if (isLast) 4.dp else 0.dp,
|
||||||
),
|
),
|
||||||
shape = when {
|
isTop = isFirst,
|
||||||
isFirst && isLast -> MaterialTheme.shapes.medium
|
isBottom = isLast,
|
||||||
isFirst -> MaterialTheme.shapes.medium.copy(
|
|
||||||
bottomEnd = CornerSize(0),
|
|
||||||
bottomStart = CornerSize(0),
|
|
||||||
)
|
|
||||||
isLast -> MaterialTheme.shapes.medium.copy(
|
|
||||||
topEnd = CornerSize(0),
|
|
||||||
topStart = CornerSize(0),
|
|
||||||
)
|
|
||||||
else -> RectangleShape
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user