Badran
07/04/2025, 1:17 PMKonstantin Tskhovrebov
07/04/2025, 1:56 PMStylianos Gakis
07/04/2025, 2:40 PMAlex Styl
07/04/2025, 3:06 PMBadran
07/04/2025, 3:25 PMBadran
07/04/2025, 3:25 PMAlex Styl
07/04/2025, 3:27 PM// Outline.kt
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.PathFillType
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
fun Modifier.outline(thickness: Dp, color: Color, shape: Shape = RectangleShape, offset: Dp = 0.dp): Modifier {
return this.drawBehind {
val strokeWidth = thickness.toPx()
val outline = shape.createOutline(size, layoutDirection, this)
when (outline) {
is Outline.Generic -> {
// not supported
}
is Outline.Rectangle -> {
val inset = offset.toPx()
val path = Path().apply {
addRect(
Rect(
left = inset - strokeWidth,
top = inset - strokeWidth,
right = size.width - inset + strokeWidth,
bottom = size.height - inset + strokeWidth
)
)
fillType = PathFillType.EvenOdd
addRect(
Rect(
left = inset,
top = inset,
right = size.width - inset,
bottom = size.height - inset
)
)
}
drawPath(path, color)
}
is Outline.Rounded -> {
val inset = offset.toPx()
val roundRect = outline.roundRect
val topLeftRadius = roundRect.topLeftCornerRadius.x
val topRightRadius = roundRect.topRightCornerRadius.x
val bottomRightRadius = roundRect.bottomRightCornerRadius.x
val bottomLeftRadius = roundRect.bottomLeftCornerRadius.y
val topLeftOutlineRadius = topLeftRadius + strokeWidth
val topRightOutlineRadius = topRightRadius + strokeWidth
val bottomRightOutlineRadius = bottomRightRadius + strokeWidth
val bottomLeftOutlineRadius = bottomLeftRadius + strokeWidth
val path = Path().apply {
addRoundRect(
RoundRect(
left = inset - strokeWidth,
top = inset - strokeWidth,
right = size.width - inset + strokeWidth,
bottom = size.height - inset + strokeWidth,
topLeftCornerRadius = CornerRadius(topLeftOutlineRadius, topLeftOutlineRadius),
topRightCornerRadius = CornerRadius(topRightOutlineRadius, topRightOutlineRadius),
bottomRightCornerRadius = CornerRadius(bottomRightOutlineRadius, bottomRightOutlineRadius),
bottomLeftCornerRadius = CornerRadius(bottomLeftOutlineRadius, bottomLeftOutlineRadius)
)
)
fillType = PathFillType.EvenOdd
addRoundRect(
RoundRect(
left = inset,
top = inset,
right = size.width - inset,
bottom = size.height - inset,
topLeftCornerRadius = CornerRadius(topLeftRadius, topLeftRadius),
topRightCornerRadius = CornerRadius(topRightRadius, topRightRadius),
bottomRightCornerRadius = CornerRadius(bottomRightRadius, bottomRightRadius),
bottomLeftCornerRadius = CornerRadius(bottomLeftRadius, bottomLeftRadius)
)
)
}
drawPath(path, color)
}
}
}
}
Alex Styl
07/04/2025, 3:28 PM// FocusRing.kt
import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
import com.composeunstyled.theme.Theme
@Composable
fun Modifier.focusRing(interactionSource: InteractionSource, shape: Shape): Modifier {
val focused by interactionSource.collectIsFocusedAsState()
val focusRingColor = if (focused) Theme[colors][focusRing] else Color.Transparent
return this.outline(2.dp, focusRingColor, shape).clip(shape)
}
Alex Styl
07/04/2025, 3:28 PMBadran
07/04/2025, 3:59 PM