Jetpack Compose 中的图像渐变
Gradient over image in Jetpack Compose
这是我的组件:
@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
,但由于缺少文档,我无法使用它。
编辑:This 是我尝试使用 Jetpack Compose 进行的操作。
哇,那个花了几个小时 ;)
您可以将 Modifier.background
与 VerticalGradient
一起使用。我使用 Column 来保存修饰符并进行计算以获得图像大小,但您的解决方案可能会有所不同,您可以以不同的方式计算或存储大小,并将修饰符放在其他地方。我在代码中留下了两个 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,
)
}
}
}
}
这是我的样本的样子:
对于 1.0.0
,您可以使用类似的东西:
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))
}
原文:
之后:
您还可以使用 .drawWithCache
modifier and the onDrawWithContent
将渐变应用到 Image()
,允许开发人员在布局内容之前或之后绘制。
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)
}
}
)
的更新答案
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
)
}
}
}
}
另外,请注意渐变如何绘制高度的控件。
输出
直截了当:
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
)
}
}
这是我的组件:
@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
,但由于缺少文档,我无法使用它。
编辑:This 是我尝试使用 Jetpack Compose 进行的操作。
哇,那个花了几个小时 ;)
您可以将 Modifier.background
与 VerticalGradient
一起使用。我使用 Column 来保存修饰符并进行计算以获得图像大小,但您的解决方案可能会有所不同,您可以以不同的方式计算或存储大小,并将修饰符放在其他地方。我在代码中留下了两个 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,
)
}
}
}
}
这是我的样本的样子:
对于 1.0.0
,您可以使用类似的东西:
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))
}
原文:
之后:
您还可以使用 .drawWithCache
modifier and the onDrawWithContent
将渐变应用到 Image()
,允许开发人员在布局内容之前或之后绘制。
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)
}
}
)
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
)
}
}
}
}
另外,请注意渐变如何绘制高度的控件。
输出
直截了当:
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
)
}
}