From 239e09544c155421f31ff79a8bc9b8976fb141a1 Mon Sep 17 00:00:00 2001 From: adamglin Date: Sat, 7 Dec 2024 13:49:14 +0800 Subject: [PATCH 1/2] test --- .../com/adamglin/composeshadow/softShadow.kt | 105 ++++++++++++++++++ .../composeshadow/utils/spreadScale.kt | 16 +++ gradle/libs.versions.toml | 2 +- .../composeshadow/app/MainActivity.kt | 49 +++++++- 4 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/softShadow.kt create mode 100644 compose-shadow/src/commonMain/kotlin/com/adamglin/composeshadow/utils/spreadScale.kt diff --git a/compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/softShadow.kt b/compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/softShadow.kt new file mode 100644 index 0000000..97a9bd2 --- /dev/null +++ b/compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/softShadow.kt @@ -0,0 +1,105 @@ +package com.adamglin.composeshadow + +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawWithCache +import androidx.compose.ui.graphics.* +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp +import com.adamglin.composeshadow.utils.spreadScale + + +/** + * A [NativePaint.setShadowLayer]/[View.LAYER_TYPE_SOFTWARE] layer type based shadow [Modifier]. + * + * You must use it with [SoftLayerShadowContainer]. + * + * @param radius The shadow radius. + * @param color The shadow color. + * @param shape The shadow shape. + * @param spread The shadow spread. + * @param offset The shadow offset. + * @param isAlphaContentClip Indicates whether the alpha (transparent) content should be clipped to the [shape]. + * @return The applied SoftLayerShadow [Modifier]. + * @see SoftLayerShadowContainer + * @author GIGAMOLE + */ +fun Modifier.softLayerShadow( + shape: Shape, + radius: Dp = 4.dp, + color: Color = Color.Black.copy(0.25f), + spread: Dp = 4.dp, + offset: DpOffset = DpOffset(4.dp, 4.dp), +): Modifier = this.drawWithCache { + val radiusPx = radius.toPx() + val isRadiusValid = radiusPx > 0.0F + val paint = Paint().apply { + this.color = if (isRadiusValid) { + Color.Transparent + } else { + color + } + + asFrameworkPaint().apply { + isDither = true + isAntiAlias = true + + if (isRadiusValid) { + setShadowLayer( + radiusPx, + offset.x.toPx(), + offset.y.toPx(), + color.toArgb() + ) + } + } + } + val shapeOutline = shape.createOutline( + size = size, + layoutDirection = LayoutDirection.Rtl, + density = this + ) + val shapePath = Path().apply { + addOutline(outline = shapeOutline) + } + + val drawShadowBlock: DrawScope.() -> Unit = { + drawIntoCanvas { canvas -> + canvas.withSave { + if (isRadiusValid.not()) { + canvas.translate( + dx = offset.x.toPx(), + dy = offset.y.toPx() + ) + } + + if (spread.value != 0.0F) { + canvas.scale( + sx = spreadScale( + spread = spread.toPx(), + size = size.width + ), + sy = spreadScale( + spread = spread.toPx(), + size = size.height + ), + pivotX = center.x, + pivotY = center.y + ) + } + + canvas.drawOutline( + outline = shapeOutline, + paint = paint + ) + } + } + } + + onDrawBehind { + drawShadowBlock() + } +} diff --git a/compose-shadow/src/commonMain/kotlin/com/adamglin/composeshadow/utils/spreadScale.kt b/compose-shadow/src/commonMain/kotlin/com/adamglin/composeshadow/utils/spreadScale.kt new file mode 100644 index 0000000..b5f45f9 --- /dev/null +++ b/compose-shadow/src/commonMain/kotlin/com/adamglin/composeshadow/utils/spreadScale.kt @@ -0,0 +1,16 @@ +package com.adamglin.composeshadow.utils + +/** + * Calculates shadow spread scale. + * + * @param spread The raw spread. + * @param size The X or Y side. + * @return The shadow spread scale. + * @see com.gigamole.composeshadowsplus.rsblur.rsBlurShadow + * @see com.gigamole.composeshadowsplus.softlayer.softLayerShadow + * @author GIGAMOLE + */ +internal fun spreadScale( + spread: Float, + size: Float +): Float = 1.0F + ((spread / size) * 2.0F) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 548416b..9108011 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] #android androidCompileSdk = "35" -androidMinSdk = "28" +androidMinSdk = "21" androidTargetSdk = "35" androidGradlePlugin = "8.6.1" #androidx diff --git a/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt b/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt index 68cdc51..a2c6006 100644 --- a/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt +++ b/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt @@ -1,17 +1,64 @@ package com.adamglin.composeshadow.app import SampleApp +import android.graphics.drawable.shapes.Shape +import android.os.Build import android.os.Bundle +import android.view.View import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView +import com.adamglin.composeshadow.softLayerShadow class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { - SampleApp() + Column { + SoftLayerShadowContainer{ + Box( + modifier = Modifier + .padding(40.dp) + .softLayerShadow( + shape = RoundedCornerShape(4.dp) + ) + .requiredSize(100.dp) + .background(Color.White) + ) + } + SampleApp() + } } } +} + +@Composable +fun SoftLayerShadowContainer(content: @Composable () -> Unit) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + AndroidView( + factory = { context -> + ComposeView(context).apply { + setLayerType(View.LAYER_TYPE_SOFTWARE, null) + setContent(content) + } + } + ) + } else { + content() + } } \ No newline at end of file From 30caa23b5dc51e0d4fdef9a18d8ba33841c10ed3 Mon Sep 17 00:00:00 2001 From: adamglin Date: Sat, 7 Dec 2024 19:14:35 +0800 Subject: [PATCH 2/2] remove code --- .../composeshadow/SoftLayerShadowContainer.kt | 26 +++++++++++++++++++ .../composeshadow/app/MainActivity.kt | 23 ++++------------ 2 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/SoftLayerShadowContainer.kt diff --git a/compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/SoftLayerShadowContainer.kt b/compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/SoftLayerShadowContainer.kt new file mode 100644 index 0000000..932c81a --- /dev/null +++ b/compose-shadow/src/androidMain/kotlin/com/adamglin/composeshadow/SoftLayerShadowContainer.kt @@ -0,0 +1,26 @@ +package com.adamglin.composeshadow + +import android.os.Build +import android.view.View +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.viewinterop.AndroidView + +@Composable +fun SoftLayerShadowContainer(content: @Composable () -> Unit) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + AndroidView( + factory = { context -> + ComposeView(context).apply { + setLayerType(View.LAYER_TYPE_SOFTWARE, null) + setContent(content) + } + }, + modifier = Modifier.fillMaxSize() + ) + } else { + content() + } +} \ No newline at end of file diff --git a/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt b/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt index a2c6006..87d8b12 100644 --- a/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt +++ b/sample/compose-app/src/androidMain/kotlin/com/adamglin/composeshadow/app/MainActivity.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView +import com.adamglin.composeshadow.SoftLayerShadowContainer import com.adamglin.composeshadow.softLayerShadow class MainActivity : ComponentActivity() { @@ -29,8 +30,9 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { - Column { - SoftLayerShadowContainer{ + SoftLayerShadowContainer{ + Column { + Box( modifier = Modifier .padding(40.dp) @@ -40,25 +42,10 @@ class MainActivity : ComponentActivity() { .requiredSize(100.dp) .background(Color.White) ) + SampleApp() } - SampleApp() } } } } -@Composable -fun SoftLayerShadowContainer(content: @Composable () -> Unit) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - AndroidView( - factory = { context -> - ComposeView(context).apply { - setLayerType(View.LAYER_TYPE_SOFTWARE, null) - setContent(content) - } - } - ) - } else { - content() - } -} \ No newline at end of file