简体   繁体   中英

Jetpack Compose icon shadow/elevation

Is there a way to have an Icon (with ImageVector) component with a shadow/elevation in Jetpack Compose?

I want to make an IconButton with an elevated Icon but there seems to be no solution available for this problem. Things like Modifier.shadow() will only draw a shadow box around my icon and the Icon component itself has no elevation parameter.

This ticket seems like a duplicate of How to add a shadow / border / elevation to an icon in Jetpack Compose at first glance, but that ticket is not referring to the Icon component in combination with an ImageVector. Also, the proposed solution does not work and it wasn't updated in 6 months.

To further clarify, I want my Icon to look like this:

带阴影的图标

What you require is a library that converts imageVectors or xml files into Path . As i know of there is no built-in library for this. There are probably few out there that converts into Path or Shape.

When you have a shape or path what you need to do is draw with this shape as Modifier or into Canvas

fun Modifier.vectorShadow(
    path: Path,
    x: Dp,
    y: Dp,
    radius: Dp
) = composed(
    inspectorInfo = {
        name = "vectorShadow"
        value = path
        value = x
        value = y
        value = radius
    },
    factory = {

        val paint = remember {
            Paint()
        }

        val frameworkPaint = remember {
            paint.asFrameworkPaint()
        }

        val color = Color.DarkGray
        val dx: Float
        val dy: Float
        val radiusInPx: Float

        with(LocalDensity.current) {
            dx = x.toPx()
            dy = y.toPx()
            radiusInPx = radius.toPx()
        }


        drawBehind {

            this.drawIntoCanvas {

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

                frameworkPaint.color = transparent

                frameworkPaint.setShadowLayer(
                    radiusInPx,
                    dx,
                    dy,
                    color
                        .copy(alpha = .7f)
                        .toArgb()
                )

                it.drawPath(path, paint)


            }
        }
    }
)

Usage

Column(
    modifier = Modifier
        .fillMaxSize()
        .padding(8.dp)
) {

    val center = with(LocalDensity.current) {
        150.dp.toPx()
    }
    val path1 = createPolygonPath(center, center, 6, center)
    val path2 = createPolygonPath(center, center, 5, center)

    Canvas(
        modifier = Modifier
            .size(300.dp)
            .vectorShadow(path1, 0.dp, 0.dp, 6.dp)
            .border(3.dp, Color.Green)
    ) {
        drawPath(path1, Color.White)
    }
    Spacer(modifier = Modifier.height(10.dp))
    Canvas(
        modifier = Modifier
            .size(300.dp)
            .vectorShadow(path2, 3.dp, 3.dp, 10.dp)
            .border(3.dp, Color.Green)
    ) {
        drawPath(path2, Color.White)
    }
}

Result

在此处输入图像描述

createPolygonPath is a sample function to create Path. If you manage to convert your vector to Path rest is simple.

fun createPolygonPath(cx: Float, cy: Float, sides: Int, radius: Float): Path {
    val angle = 2.0 * Math.PI / sides

    return Path().apply {
        moveTo(
            cx + (radius * cos(0.0)).toFloat(),
            cy + (radius * sin(0.0)).toFloat()
        )
        for (i in 1 until sides) {
            lineTo(
                cx + (radius * cos(angle * i)).toFloat(),
                cy + (radius * sin(angle * i)).toFloat()
            )
        }
        close()
    }
}

It's not exactly what you want but for elevating an icon you can simply do this:

Icon(
    Icons.Outlined.Refresh, contentDescription = "back",
    modifier = Modifier
        .size(300.dp)
        .offset(10.dp, 10.dp), tint = Color(0, 0, 0, 40)
)
Icon(
    Icons.Outlined.Refresh, contentDescription = "front",
    modifier = Modifier.size(300.dp), tint = Color(0xFFb6d7a8)
)

在此处输入图像描述

The problem is that it is lacking the blurring effect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM