All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.FocusRingIndication.kt Maven / Gradle / Ivy

package com.composables.core

import androidx.compose.foundation.Indication
import androidx.compose.foundation.IndicationInstance
import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp


@Composable
public fun rememberFocusRingIndication(
    ringColor: Color = Color.Unspecified,
    ringWidth: Dp = Dp.Unspecified,
    paddingValues: PaddingValues = PaddingValues(),
    cornerRadius: Dp
): Indication {
    return remember { FocusRingIndication(ringColor, ringWidth, paddingValues, cornerRadius) }
}

internal class FocusRingIndication internal constructor(
    private val ringColor: Color,
    private val strokeWidth: Dp,
    private val paddingValues: PaddingValues,
    private val cornerRadius: Dp,
) : Indication {

    @Composable
    override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance {
        val isFocused = interactionSource.collectIsFocusedAsState()
        val layoutDirection = LocalLayoutDirection.current
        return remember(interactionSource, layoutDirection) {
            object : IndicationInstance {
                override fun ContentDrawScope.drawIndication() {
                    drawContent()
                    if (isFocused.value) {
                        val cornerRadiusObj = CornerRadius(cornerRadius.toPx())
                        val ringWidthFloat = strokeWidth.toPx()

                        val paddingFloatTop = paddingValues.calculateTopPadding().toPx()
                        val paddingFloatBottom = paddingValues.calculateBottomPadding().toPx()
                        val paddingFloatStart = paddingValues.calculateStartPadding(layoutDirection).toPx()
                        val paddingFloatEnd = paddingValues.calculateEndPadding(layoutDirection).toPx()

                        val ringSize = Size(
                            width = size.width + paddingFloatStart + paddingFloatEnd,
                            height = size.height + paddingFloatTop + paddingFloatBottom
                        )

                        val topLeft = Offset(-paddingFloatStart, -paddingFloatTop)

                        val ringPath = Path().apply {
                            addRoundRect(
                                RoundRect(
                                    rect = Rect(offset = topLeft, size = ringSize),
                                    cornerRadius = cornerRadiusObj
                                )
                            )
                        }
                        drawPath(ringPath, color = ringColor, style = Stroke(width = ringWidthFloat))
                    }
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy