Files
AndroidLiquidGlass/liquid-glass/src/main/java/com/kyant/liquidglass/GlassBorder.kt
T
2025-07-24 09:17:25 +08:00

99 lines
3.0 KiB
Kotlin

package com.kyant.liquidglass
import android.graphics.RenderEffect
import android.graphics.RuntimeShader
import android.graphics.Shader
import android.os.Build
import androidx.annotation.FloatRange
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import kotlin.math.PI
@Immutable
sealed interface GlassBorder {
val width: Dp
@get:FloatRange(from = 0.0, to = 1.0)
val intensity: Float
@Stable
fun createRenderEffect(density: Density, size: Size, cornerRadius: Float): RenderEffect? {
return null
}
@Immutable
data object None : GlassBorder {
override val width: Dp = Dp.Unspecified
override val intensity: Float = 0f
}
@Immutable
data class Solid(
override val width: Dp = 2.dp,
@param:FloatRange(from = 0.0, to = 1.0) override val intensity: Float = 0.4f
) : GlassBorder
@Immutable
data class Highlight(
override val width: Dp = 2.dp,
@param:FloatRange(from = 0.0, to = 1.0) override val intensity: Float = 0.4f,
val angle: Float = 45f,
val decay: Float = 1f
) : GlassBorder {
private var highlightShaderCache: RuntimeShader? = null
override fun createRenderEffect(density: Density, size: Size, cornerRadius: Float): RenderEffect? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val blurRenderEffect =
cachedBlurRenderEffect
?: RenderEffect.createBlurEffect(
with(density) { 0.5f.dp.toPx() },
with(density) { 0.5f.dp.toPx() },
Shader.TileMode.DECAL
).also { cachedBlurRenderEffect = it }
val highlightShader = highlightShaderCache
?: RuntimeShader(LiquidGlassShaders.highlightShaderString)
.also { highlightShaderCache = it }
val highlightRenderEffect =
RenderEffect.createRuntimeShaderEffect(
highlightShader.apply {
setFloatUniform("size", size.width, size.height)
setFloatUniform("cornerRadius", cornerRadius)
setFloatUniform("angle", angle * PI.toFloat() / 180f)
setFloatUniform("decay", decay)
},
"image"
)
RenderEffect.createChainEffect(
highlightRenderEffect,
blurRenderEffect
)
} else {
null
}
}
private companion object {
var cachedBlurRenderEffect: RenderEffect? = null
}
}
companion object {
@Stable
val Default: Highlight = Highlight()
}
}