gpt4 book ai didi

android - 如何在 Jetpack Compose 中向 ImageView 添加对角色带?

转载 作者:行者123 更新时间:2023-12-05 09:00:52 24 4
gpt4 key购买 nike

根据设计,我们的 ImageView 应该在 View 顶部添加一个标签。此标签应包含文本,例如“50%”,表示图片中的商品已打折 50%。

如何在 Jetpack Compose 中的现有 ImageView 之上绘制这样的标签/丝带?

编辑:使用的图像是来自 URL 的图像,如果这很重要,当前正在使用 Coil 的“AsyncImage”加载

提前致谢! Example of the image view

最佳答案

解决这个问题需要简单的数学运算、带旋转功能的 Drawscope、用于测量文本宽度和高度的 TextMeasurer。如果您希望将这些作为修饰符,则组成修饰符。构建一个具有纯色背景的另一个具有微光效果。您可以在应用这些修饰符之前检查 painter.state 是否成功。

结果

enter image description here

修改器实现

fun Modifier.drawDiagonalLabel(
text: String,
color: Color,
style: TextStyle = TextStyle(
fontSize = 18.sp,
fontWeight = FontWeight.SemiBold,
color = Color.White
),
labelTextRatio: Float = 7f
) = composed(
factory = {

val textMeasurer = rememberTextMeasurer()
val textLayoutResult: TextLayoutResult = remember {
textMeasurer.measure(text = AnnotatedString(text), style = style)
}


Modifier
.clipToBounds()
.drawWithContent {
val canvasWidth = size.width
val canvasHeight = size.height

val textSize = textLayoutResult.size
val textWidth = textSize.width
val textHeight = textSize.height

val rectWidth = textWidth * labelTextRatio
val rectHeight = textHeight * 1.1f

val rect = Rect(
offset = Offset(canvasWidth - rectWidth, 0f),
size = Size(rectWidth, rectHeight)
)

val sqrt = sqrt(rectWidth / 2f)
val translatePos = sqrt * sqrt

drawContent()
withTransform(
{
rotate(
degrees = 45f,
pivot = Offset(
canvasWidth - rectWidth / 2,
translatePos
)
)
}
) {
drawRect(
color = color,
topLeft = rect.topLeft,
size = rect.size
)
drawText(
textMeasurer = textMeasurer,
text = text,
style = style,
topLeft = Offset(
rect.left + (rectWidth - textWidth) / 2f,
rect.top + (rect.bottom - textHeight) / 2f
)
)
}

}
}
)


fun Modifier.drawDiagonalShimmerLabel(
text: String,
color: Color,
style: TextStyle = TextStyle(
fontSize = 18.sp,
fontWeight = FontWeight.SemiBold,
color = Color.White
),
labelTextRatio: Float = 7f,
) = composed(
factory = {

val textMeasurer = rememberTextMeasurer()
val textLayoutResult: TextLayoutResult = remember {
textMeasurer.measure(text = AnnotatedString(text), style = style)
}

val transition = rememberInfiniteTransition()

val progress by transition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(3000, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
)
)

Modifier
.clipToBounds()
.drawWithContent {
val canvasWidth = size.width
val canvasHeight = size.height

val textSize = textLayoutResult.size
val textWidth = textSize.width
val textHeight = textSize.height

val rectWidth = textWidth * labelTextRatio
val rectHeight = textHeight * 1.1f

val rect = Rect(
offset = Offset(canvasWidth - rectWidth, 0f),
size = Size(rectWidth, rectHeight)
)

val sqrt = sqrt(rectWidth / 2f)
val translatePos = sqrt * sqrt

val brush = Brush.linearGradient(
colors = listOf(
color,
style.color,
color,
),
start = Offset(progress * canvasWidth, progress * canvasHeight),
end = Offset(
x = progress * canvasWidth + rectHeight,
y = progress * canvasHeight + rectHeight
),
)

drawContent()
withTransform(
{
rotate(
degrees = 45f,
pivot = Offset(
canvasWidth - rectWidth / 2,
translatePos
)
)
}
) {
drawRect(
brush = brush,
topLeft = rect.topLeft,
size = rect.size
)
drawText(
textMeasurer = textMeasurer,
text = text,
style = style,
topLeft = Offset(
rect.left + (rectWidth - textWidth) / 2f,
rect.top + (rect.bottom - textHeight) / 2f
)
)
}

}
}
)

用法

Column(
modifier = Modifier
.background(backgroundColor)
.fillMaxSize()
.padding(20.dp)
) {
val painter1 = rememberAsyncImagePainter(
model = ImageRequest.Builder(LocalContext.current)
.data("https://www.techtoyreviews.com/wp-content/uploads/2020/09/5152094_Cover_PS5.jpg")
.size(coil.size.Size.ORIGINAL) // Set the target size to load the image at.
.build()
)

Image(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(4 / 3f)
.then(
if (painter1.state is AsyncImagePainter.State.Success) {
Modifier.drawDiagonalLabel(
text = "50%",
color = Color.Red
)
} else Modifier
),
painter = painter1,
contentScale = ContentScale.FillBounds,
contentDescription = null
)

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

val painter2 = rememberAsyncImagePainter(
model = ImageRequest.Builder(LocalContext.current)
.data("https://i02.appmifile.com/images/2019/06/03/03ab1861-42fe-4137-b7df-2840d9d3a7f5.png")
.size(coil.size.Size.ORIGINAL) // Set the target size to load the image at.
.build()
)

Image(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(4 / 3f)
.then(
if (painter2.state is AsyncImagePainter.State.Success) {
Modifier.drawDiagonalShimmerLabel(
text = "40% OFF",
color = Color(0xff4CAF50),
labelTextRatio = 5f
)
} else Modifier
),
painter = painter2,
contentScale = ContentScale.FillBounds,
contentDescription = null
)
}

没有任何状态绘制到图像

enter image description here

@Composable
private fun RibbonSample() {

val text = "50%"
val textMeasurer = rememberTextMeasurer()
val style = TextStyle(
fontSize = 18.sp,
fontWeight = FontWeight.SemiBold,
color = Color.White
)
val textLayoutResult: TextLayoutResult = remember {
textMeasurer.measure(text = AnnotatedString(text), style = style)
}

Box(
modifier = Modifier
.clipToBounds()
.drawWithContent {

val canvasWidth = size.width

val textSize = textLayoutResult.size
val textWidth = textSize.width
val textHeight = textSize.height

val rectWidth = textWidth * 7f
val rectHeight = textHeight * 1.1f

val rect = Rect(
offset = Offset(canvasWidth - rectWidth, 0f),
size = Size(rectWidth, rectHeight)
)

val translatePos = sqrt(rectWidth / 2f) * sqrt(rectWidth / 2f)

drawContent()
withTransform(
{
rotate(
degrees = 45f,
pivot = Offset(
canvasWidth - rectWidth / 2,
translatePos
)
)
}
) {
drawRect(
Color.Red,
topLeft = rect.topLeft,
size = rect.size
)
drawText(
textMeasurer = textMeasurer,
text = text,
style = style,
topLeft = Offset(
rect.left + (rectWidth - textWidth) / 2f,
rect.top + (rect.bottom - textHeight) / 2f
)
)
}

}
) {
Image(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(4 / 3f),
painter = painterResource(id = R.drawable.landscape1),
contentScale = ContentScale.FillBounds,
contentDescription = null
)
}
}

关于android - 如何在 Jetpack Compose 中向 ImageView 添加对角色带?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74742032/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com