Manuel Lucas
Manuel Lucas

Reputation: 542

Remove default elevation from image in Jetpack Compose

I would like to know if there some way to specify to Jetpack Compose plugin to remove default elevation from Image component, or the only wy is rebuild the image asset.

I have this:

Image(
                    painter = painterResource(id = if(sessionToken.isNotEmpty()) R.drawable.ic_disa_logo else R.drawable.ic_cepsa_logo),
                    contentDescription = "login_logo",
                    modifier = Modifier
                        .align(CenterHorizontally)
                        .fillMaxWidth()


Which show like this

enter image description here

As you can check the image have a elevatioon which I'm not adding to the component, so Should I recreate the asset, or is there some way to remove it.

Thanks in advance !

[EDIT]

As the suggestion I try to use a custom shape to hide the border of the image make an implementation of the solution like this:

 val offset = with(LocalDensity.current){
        4.dp.toPx()
    }


    val customCircleShape = GenericShape{ size: Size, layoutDirection: LayoutDirection ->
        addOval(
            Rect(
                offset = Offset(
                    offset, offset
                ),
                size = Size(
                    width = size.width - 2 * offset,
                    height = size.height - 2 * offset
                )
            )
        )
    }
Column(
                verticalArrangement = Arrangement.Top,
                modifier = Modifier
                    .clip(customCircleShape)
                    .shadow(4.dp, CircleShape)
                    .size(60.dp)
                    .background(Color.White)
            ) {
                Image(
                    painter = painterResource(id = if (sessionToken.isNotEmpty()) R.drawable.ic_disa_logo else R.drawable.ic_cepsa_logo),
                    contentDescription = "login_logo",
                    modifier = Modifier
                        .align(Alignment.CenterHorizontally)
                        .fillMaxWidth()
                        .fillMaxHeight(0.25f)
                        .border(BorderStroke(2.dp, Color.White), CircleShape)
                        .background(Color.White)
                )
            }

But the border is still showing as the firts picture I added it

What Am I missing here?

[EDIT]

Doesn't matter how big a do the circle which supose to hide the shadow, don't do it.

I add the picture i'm using as reference.

enter image description here

[SOLUTION]

I make works doing this:

val offset = with(LocalDensity.current){
        8.dp.toPx()
    }

    val customCircleShape = GenericShape { size: Size, layoutDirection: LayoutDirection ->
        addOval(
            Rect(
                offset = Offset(
                    offset, offset
                ),
                size = Size(
                    width = size.width - 2 * offset,
                    height = size.height - 2 * offset
                )
            )
        )
    }

Image(
                    painter = painterResource(id = if(sessionToken.isNotEmpty()) R.drawable.ic_disa_logo else R.drawable.ic_cepsa_logo),
                    contentDescription = "login_logo",
                    contentScale = ContentScale.FillBounds,
                    modifier = Modifier
                        .align(CenterHorizontally)
                        .padding(10.dp)
                        .background(Color.White)
                        .clip(customCircleShape)
                        .size(80.dp),

                )

enter image description here

Upvotes: 1

Views: 609

Answers (2)

Thracian
Thracian

Reputation: 67248

Since your logo can be contained inside a Circle you can do it in several ways.

1- Using a Path and clipPath function inside drawScope of Modifier.drawWithContent.

2- Creating a custom Circle shape that has smaller dimensions as in option 1 and applying Modifier.clip(customShape)

3- Using BlendMode with destination drawCircle inside Modifier.drawWithContent.

Since i don't have you logo. I created an Image that draws a red Circle with some shadow.

@Preview
@Composable
private fun MyImage() {
    Canvas(
        modifier = Modifier
            .shadow(4.dp, CircleShape)
            .size(60.dp)
            .background(Color.White)
    ) {

        drawCircle(color = Color.Red, radius = size.width / 2 - 5.dp.toPx())
    }
}

And implemented this Modifier as

@Preview
@Composable
fun Test() {
    Column(modifier = Modifier.fillMaxSize()) {

        Text(text = "Original")
        MyImage()

        Spacer(modifier = Modifier.height(10.dp))

        val path = remember {
            androidx.compose.ui.graphics.Path()
        }

        val offset = with(LocalDensity.current){
            4.dp.toPx()
        }


        val customCircleShape = GenericShape{size: Size, layoutDirection: LayoutDirection ->
            addOval(
                Rect(
                    offset = Offset(
                        offset, offset
                    ),
                    size = Size(
                        width = size.width - 2 * offset,
                        height = size.height - 2 * offset
                    )
                )
            )
        }

        Spacer(modifier = Modifier.height(10.dp))

        Text(text = "Clip with Shape")
        Box(modifier = Modifier.clip(customCircleShape)){
            MyImage()
        }
        Spacer(modifier = Modifier.height(10.dp))

        Text(text = "drawWithContent and clipPath")

        Box(
            modifier = Modifier.drawWithContent {


                if (path.isEmpty) {
                    path.addOval(
                        oval = Rect(
                            offset = Offset(
                                offset, offset
                            ),
                            size = Size(
                                width = size.width - 2 * offset,
                                height = size.height - 2 * offset
                            )
                        )
                    )
                }

                clipPath(path = path, clipOp = ClipOp.Intersect) {
                    [email protected]()

                }
            }
        ) {
            MyImage()
        }
    }
}

Result

enter image description here

The trick is to create a Rect for oval that which has offsets in both directions.

For BlendMode sample you can check out the link below. I clipped out an image and Button to squircle shape.

How to clip or cut a Composable?

Edit

With the image provided it's as

enter image description here

Only used clip with custom shape option but other options can be applied either to clip and add your custom shadow as i did.

@Preview
@Composable
private fun Test() {


    val offset = with(LocalDensity.current) {
        8.dp.toPx()
    }


    val customCircleShape = GenericShape { size: Size, layoutDirection: LayoutDirection ->
        addOval(
            Rect(
                offset = Offset(
                    offset, offset
                ),
                size = Size(
                    width = size.width - 2 * offset,
                    height = size.height - 2 * offset
                )
            )
        )
    }

    Column(
        Modifier
            .fillMaxSize()
            .padding(20.dp)
    ) {

        Text("ORIGINAL")

        Image(
            painter = painterResource(id = R.drawable.shell),
            contentDescription = null,
            contentScale = ContentScale.FillBounds,
        )

        Text("Clipped with Shape")

        Image(
            modifier = Modifier
                .border(1.dp, Color.Green)
                .clip(customCircleShape),
            painter = painterResource(id = R.drawable.shell),
            contentDescription = null,
            contentScale = ContentScale.FillBounds
        )


        Text("With Size and attached Modifier.shadow after")

        Image(
            modifier = Modifier
                .border(1.dp, Color.Green)
                .padding(10.dp)
                .shadow(6.dp, spotColor = Color.Cyan, shape = CircleShape)
                .background(Color.White)
                .clip(customCircleShape)
                .size(80.dp),
            painter = painterResource(id = R.drawable.shell),
            contentDescription = null,
            contentScale = ContentScale.FillBounds
        )
    }
}

Upvotes: 3

viethoang
viethoang

Reputation: 156

Have you considered trying to create a custom shadow effect?

modifier = Modifier
                .size(100.dp)
                .clip(CircleShape)
                .shadow(elevation = 0.dp, shape = CircleShape)

Upvotes: 0

Related Questions