Jetpack Compose 中的图像渐变

问题描述 投票:0回答:6

这是我的组件:

@Composable
fun Cover(
    name: String,
    imageRes: Int,
    modifier: Modifier = Modifier.padding(16.dp, 8.dp)
) {
    Box(modifier) {
        Card(
            shape = RoundedCornerShape(4.dp),
            backgroundColor = MaterialTheme.colors.secondary,
            elevation = 4.dp
        ) {
            Stack {
                Image(
                    imageResource(imageRes),
                    modifier = Modifier
                        .gravity(Alignment.Center)
                        .aspectRatio(2f),
                    contentScale = ContentScale.Crop,
                )

                Text(
                    text = name,
                    modifier = Modifier
                        .gravity(Alignment.BottomStart)
                        .padding(8.dp),
                    style = MaterialTheme.typography.h6
                )
            }
        }
    }
}

这就是它的样子:

我想在

Image
上方和
Text
后面显示深色渐变,以便文本易于阅读。我想我必须使用
LinearGradient
RadialGradient
但由于缺乏文档,我无法做到这一点。

编辑:是我正在尝试使用 Jetpack Compose 做的事情。

android gradient android-jetpack-compose
6个回答
33
投票

你可以使用类似的东西:

var sizeImage by remember { mutableStateOf(IntSize.Zero) }

val gradient = Brush.verticalGradient(
    colors = listOf(Color.Transparent, Color.Black),
    startY = sizeImage.height.toFloat()/3,  // 1/3
    endY = sizeImage.height.toFloat()
)

Box(){
    Image(painter = painterResource(id = R.drawable.banner),
        contentDescription = "",
    modifier = Modifier.onGloballyPositioned {
        sizeImage = it.size
    })
    Box(modifier = Modifier.matchParentSize().background(gradient))
}

原文:

之后:

您还可以使用

Image()
 修改器和 
.drawWithCache
 将渐变应用到 
onDrawWithContent
,允许开发人员在布局内容之前或之后进行绘制。

  Image(painter = painterResource(id = R.drawable.conero),
      contentDescription = "",
      modifier = Modifier.drawWithCache {
          val gradient = Brush.verticalGradient(
              colors = listOf(Color.Transparent, Color.Black),
              startY = size.height/3,
              endY = size.height
          )
          onDrawWithContent {
              drawContent()
              drawRect(gradient,blendMode = BlendMode.Multiply)
          }
      }
  )


11
投票

哇,那花了几个小时;)

您可以将

Modifier.background
VerticalGradient
一起使用。我使用列来保存修改器并进行计算以获得图像大小,但您的解决方案可能有所不同,您可以以不同的方式计算或存储大小,然后将修改器放在其他地方。我在代码中留下了两个 TODO,以便您可以调整渐变。

@Composable
fun Cover(
    name: String,
    imageRes: Int,
    modifier: Modifier = Modifier.padding(16.dp, 8.dp)
) {
    val density = DensityAmbient.current.density
    val width = remember { mutableStateOf(0f) }
    val height = remember { mutableStateOf(0f) }
    Box(modifier) {
        Card(
            shape = RoundedCornerShape(4.dp),
            backgroundColor = MaterialTheme.colors.secondary,
            elevation = 4.dp
        ) {
            Stack {
                Image(
                    imageResource(imageRes),
                    modifier = Modifier
                        .gravity(Alignment.Center)
                        .aspectRatio(2f)
                        .onPositioned {
                            width.value = it.size.width / density
                            height.value = it.size.height / density
                        },
                    contentScale = ContentScale.Crop,
                )
                Column(
                    Modifier.size(width.value.dp, height.value.dp)
                        .background(
                            VerticalGradient(
                                listOf(Color.Transparent, Color.Black),
                                0f,  // TODO: set start
                                500f,  // TODO: set end
                            )
                        )
                ) {}
                Text(
                    text = name,
                    modifier = Modifier.gravity(Alignment.BottomStart)
                        .padding(8.dp),
                    style = typography.h6,
                )
            }
        }
    }
}

这就是我的示例的样子:


9
投票

撰写版本
1.2.1
2022-08-22

import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

@Composable
fun Cover(
    name: String,
    @DrawableRes imageRes: Int,
    modifier: Modifier = Modifier
) {
    Box(modifier.padding(16.dp, 8.dp)) {
        Card(shape = RoundedCornerShape(4.dp)) {
            Box {
                Image(
                    painter = painterResource(imageRes),
                    contentDescription = "image: $name",
                    modifier = Modifier
                        .align(Alignment.Center),
                    contentScale = ContentScale.Crop
                )
                Text(
                    text = name,
                    modifier = Modifier
                        .align(Alignment.BottomStart)
                        .fillMaxWidth()
                        .background(
                            Brush.verticalGradient(
                                0F to Color.Transparent,
                                .5F to Color.Black.copy(alpha = 0.5F),
                                1F to Color.Black.copy(alpha = 0.8F)
                            )
                        )
                        .padding(start = 8.dp, end = 8.dp, bottom = 8.dp, top = 24.dp),
                    color = Color.White
                )
            }
        }
    }
}

@Preview
@Composable
fun ComicsPreview() {
    Cover(
        "Comics",
        R.drawable.comics
    )
}

@vitor-ramos

的更新答案

1.0.0-alpha09

import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.AmbientDensity
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.unit.dp
import tech.abd3lraouf.learn.compose.kombose.ui.theme.typography

@Composable
fun Cover(
    name: String,
    @DrawableRes imageRes: Int,
    modifier: Modifier = Modifier
) {
    val image = imageResource(imageRes)
    val density = AmbientDensity.current.density
    val width = remember { mutableStateOf(0f) }
    val height = remember { mutableStateOf(0f) }
    Box(
        modifier
            .padding(16.dp, 8.dp)
    ) {
        Card(
            shape = RoundedCornerShape(4.dp),
            backgroundColor = MaterialTheme.colors.secondary,
            elevation = 4.dp
        ) {
            Box {
                Image(
                    image,
                    modifier = Modifier
                        .align(Alignment.Center)
                        .aspectRatio(2f)
                        .onGloballyPositioned {
                            width.value = it.size.width / density
                            height.value = it.size.height / density
                        },
                    contentScale = ContentScale.Crop,
                )
                Column(
                    Modifier
                        .size(width.value.dp, height.value.dp)
                        .background(
                            Brush.verticalGradient(
                                listOf(Color.Transparent, Color.Black),
                                image.height * 0.6F,
                                image.height * 1F
                            )
                        )
                ) {}
                Text(
                    text = name,
                    modifier = Modifier
                        .align(Alignment.BottomStart)
                        .padding(8.dp),
                    style = typography.body2,
                    color = Color.White
                )
            }
        }
    }
}

另外,请注意渐变如何绘制其高度的控制。

输出


6
投票

你也可以尝试这个方法

Image(
  painterResource(R.drawable.something),
  null,
  Modifier
  .drawWithCache {
    onDrawWithContent {
      drawContent()
      drawRect(Brush.verticalGradient(
        0.5f to Color.White.copy(alpha=0F), 
        1F to Color.White
      ))
    }
  },
)

3
投票

直接说:

        Card(shape = RoundedCornerShape(8.dp)) {
        Box {
            Image(...)
            Text(
                text = "title",
                modifier = Modifier
                    .align(Alignment.BottomCenter)
                    .fillMaxWidth()
                    .background(Brush.verticalGradient(0F to Color.Transparent, .5F to Color.Red, 1F to Color.Red))
                    .padding(start = 8.dp, end = 8.dp, bottom = 8.dp, top = 16.dp),
                color = Color.White,
                style = MaterialTheme.typography.body1,
                textAlign = TextAlign.Start
            )
        }
    }

0
投票
AsyncImage(
                    model = topics[index].coverPhoto.urls.regularUrl,
                    contentDescription = null,
                    contentScale = ContentScale.Crop,
                    modifier = Modifier.wrapContentWidth()
                        .height(120.dp)
                        .padding(vertical = 8.dp)
                        .clip(RoundedCornerShape(16.dp))
                        .drawWithCache {
                            val gradient = Brush.verticalGradient(
                                colors = listOf(Color.Transparent, Color.Black),
                                startY = size.height / 3,
                                endY = size.height
                            )
                            onDrawWithContent {
                                drawContent()
                                drawRect(gradient, blendMode = BlendMode.Multiply)
                            }
                        }
                )

您可以尝试像这样的图像组合。

© www.soinside.com 2019 - 2024. All rights reserved.