Jetpack Compose 内阴影

7
如何在Jetpack Compose中创建内部阴影?该渐变应从外部的黑色到内部的透明色运行。Modifier.shadow()仅用于外部阴影。使用负海拔不起作用。
3个回答

7

enter image description here

fun Modifier.innerShadow(
    color: Color = Color.Black,
    cornersRadius: Dp = 0.dp,
    spread: Dp = 0.dp,
    blur: Dp = 0.dp,
    offsetY: Dp = 0.dp,
    offsetX: Dp = 0.dp
) = drawWithContent {

    drawContent()

    val rect = Rect(Offset.Zero, size)
    val paint = Paint()

    drawIntoCanvas {

        paint.color = color
        paint.isAntiAlias = true
        it.saveLayer(rect, paint)
        it.drawRoundRect(
            left = rect.left,
            top = rect.top,
            right = rect.right,
            bottom = rect.bottom,
            cornersRadius.toPx(),
            cornersRadius.toPx(),
            paint
         )
         val frameworkPaint = paint.asFrameworkPaint()
         frameworkPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
         if (blur.toPx() > 0) {
             frameworkPaint.maskFilter = BlurMaskFilter(blur.toPx(), BlurMaskFilter.Blur.NORMAL)
         }
         val left = if (offsetX > 0.dp) {
             rect.left + offsetX.toPx()
         } else {
             rect.left
         }
         val top = if (offsetY > 0.dp) {
             rect.top + offsetY.toPx()
         } else {
             rect.top
         }
         val right = if (offsetX < 0.dp) {
             rect.right + offsetX.toPx()
         } else {
             rect.right
         }
         val bottom = if (offsetY < 0.dp) {
             rect.bottom + offsetY.toPx()
         } else {
             rect.bottom
         }
         paint.color = Color.Black
         it.drawRoundRect(
             left = left + spread.toPx() / 2,
             top = top + spread.toPx() / 2,
             right = right - spread.toPx() / 2,
             bottom = bottom - spread.toPx() / 2,
             cornersRadius.toPx(),
             cornersRadius.toPx(),
             paint
         )
         frameworkPaint.xfermode = null
         frameworkPaint.maskFilter = null
    }
}

用法:

Box(
    modifier = Modifier
        .width(240.dp)
        .height(180.dp)
        .outerShadow(
            color = Color(0xff000000),
            alpha = 0.5f,
            cornersRadius = 20.dp,
            shadowBlurRadius = 30.dp,
            offsetX = 0.dp,
            offsetY = 15.dp
        )
        .clip(RoundedCornerShape(20.dp))
        .background(Color(0xFF282A2F))
        .innerShadow(
            blur = 1.dp,
            color = Color(0xff00FFFF),
            cornersRadius = 20.dp,
            offsetX = (-40.5).dp,
            offsetY = (-10.5).dp
        )
        .innerShadow(
            blur = 20.dp,
            color = Color(0xffff0000),
            cornersRadius = 20.dp,
            offsetX = 0.5.dp,
            offsetY = 0.5.dp
        )
        .padding(14.dp),
    contentAlignment = Alignment.Center
) {
    Text(
        text = stringResource(id = R.string.notification_service),
        modifier = Modifier,
        color = Color.White
     )
}

希望这能帮到您。

outerShadow 也是一个自定义修饰符,从其他网站复制而来。


运行良好。谢谢! - ya man
5
请问您能否添加外阴影的链接?我非常需要它。 - ziXiong
对于外部阴影,请查看此链接:https://www.youtube.com/watch?v=LqvaiNmVIaI 示例代码:https://github.com/Debdutta-Panda/CustomShadow - moonlady16

6

Modifier.shadow 相对于 Modifier.background 的位置将阴影放在组件内部。此外,您还可以创建 Modifier.drawWithContentframeworkPaint 以带有模糊的方式绘制阴影。

Column(
    modifier = Modifier
        .fillMaxSize()
        .padding(20.dp)
) {
    ComponentWithInnerShadow()
    Spacer(modifier = Modifier.height(12.dp))
    ComponentWithOuterShadow()
    Spacer(modifier = Modifier.height(12.dp))
    ComponentWithCustomInnerShadow()
}

@Composable private fun ComponentWithInnerShadow() {
    Column(
        modifier = Modifier
            .clip(RoundedCornerShape(5.dp))
            .background(Color.Yellow)
            .shadow(2.dp, shape = RoundedCornerShape(5.dp))
    ) {
        Text(text = "Hello World", modifier = Modifier.padding(12.dp))
    } }

@Composable
private fun ComponentWithOuterShadow() {
    Column(
        modifier = Modifier
            .shadow(2.dp, shape = RoundedCornerShape(5.dp))
            .background(Color.Yellow)

    ) {
        Text(text = "Hello World", modifier = Modifier.padding(12.dp))
    }
}

@Composable
private  fun ComponentWithCustomInnerShadow() {
    Column(
        modifier = Modifier.innerShadow()

    ) {
        Text(text = "Hello World", modifier = Modifier.padding(12.dp))
    }
}

使用组合修饰符。我没有设置参数,只是设置了任意数字,您可以设置自己的参数,并且如果需要,设置颜色。虽然此选项比标准内部阴影更好看,但您仍需要为前景和形状提供颜色。我为演示设置了颜色并绘制了圆角矩形。

fun Modifier.innerShadow() = composed(
    inspectorInfo = {

    },
    factory = {

        val paint = remember() {
            Paint()
        }

        val foregroundPaint = remember() {
            Paint().apply {
                color = Color.Yellow
            }
        }

        val frameworkPaint = remember {
            paint.asFrameworkPaint()
        }

        Modifier.drawWithContent {
            this.drawIntoCanvas {
                val color = Color.LightGray

                val radius = 2.dp.toPx()

                val shadowColor = color
                    .copy(alpha = .7f)
                    .toArgb()
                val transparent = color
                    .copy(alpha = 0f)
                    .toArgb()

                frameworkPaint.color = transparent

                frameworkPaint.setShadowLayer(
                    radius,
                    0f,
                    0f,
                    shadowColor
                )
                val shadowRadius = 4.dp.toPx()

                it.drawRoundRect(
                    left = 0f,
                    top = 0f,
                    right = this.size.width,
                    bottom = this.size.height,
                    radiusX = 5.dp.toPx(),
                    radiusY = 5.dp.toPx(),
                    paint = foregroundPaint
                )

                it.drawRoundRect(
                    left = 0f,
                    top = 0f,
                    right = this.size.width,
                    bottom = this.size.height,
                    radiusX = 5.dp.toPx(),
                    radiusY = 5.dp.toPx(),
                    paint = paint
                )

                it.drawRoundRect(
                    left = shadowRadius,
                    top = shadowRadius,
                    right = this.size.width - shadowRadius,
                    bottom = this.size.height - shadowRadius,
                    radiusX = 5.dp.toPx(),
                    radiusY = 5.dp.toPx(),
                    paint = foregroundPaint
                )
                drawContent()

            }
        }
    }
)

enter image description here


谢谢您的回答,但是渐变应该向中间透明。 - ya man
frameworkPaint.setShadowLayer sets shadow position and blur not gradient and it's generally used for drawing shadow, i use it to draw colored shadow as you can see here. You need to play with those values or you can draw gradient instead of drawRoundRect(paint = paint ) - Thracian
我上一篇文章是为了演示如何使用模糊、合成和绘制自定义形状,其中包含任意数字。setShadowLayer(radius, dx, dy)中,radius改变模糊半径,dx当为正数时将阴影设置到右侧,dy则为向下。 - Thracian

0

虽然不支持此功能,但您有其他选择:

  1. 使用带有渐变画刷的边框修饰符
  2. 使用Android Canvas
  3. 使用渐变和Modifier.drawBehind在内容下方绘制内嵌阴影

源代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接