如何使用Jetpack Compose中的Coil制作初始图标。

huangapple go评论106阅读模式
英文:

How to make initials icons using Coil in Jetpack Compose

问题

So I am using the Coil library for our image processing and I noticed in the placeholder it only takes an int. I want, however, to display initials if a user does not have an avatar or in case of any error show initials, like this image below. Problem is, I am new in Jetpack Compose and not sure how I can achieve this. See my code below.

如何使用Jetpack Compose中的Coil制作初始图标。

I have this card that has an icon and some details, my Profile Card

ProfileCard(
personName = String.format("%s %s", e.firstName, e.lastName),
personC = entity.program ?: "",
painter = rememberAsyncImagePainter(model = getProfileAvatar(entity.id)),
onCardClick = {})

My getProfileAvatar()

private fun getProfileAvatar(id: String) : ImageRequest {
val url = ServiceAPI.photoUrl(id)
return ImageRequest.Builder(requireContext())
.data(url)
.addHeader() )
.build() }

Will appreciate feedback, I did see a couple of posts, but don't address the Jetpack part.

英文:

So I am using the Coil library for our image processing and I noticed in the place holder it only takes an int. I want however to display initials if a user does not have an avatar or incase of any error show initials, like this image see below. Problem is, I am new in jetpack compose and not sure how I can achieve this. See my code below.

如何使用Jetpack Compose中的Coil制作初始图标。

I have this card that has icon, and some details my Profile Card

  1. ProfileCard(
  2. personName = String.format("%s %s", e.firstName, e.lastName),
  3. personC = entity.program ?: "",
  4. painter = rememberAsyncImagePainter(model = getProfileAvatar(entity.id)),
  5. onCardClick = {})

My getProfileAvatar()

  1. private fun getProfileAvatar(id: String) : ImageRequest {
  2. val url = ServiceAPI.photoUrl(id)
  3. return ImageRequest.Builder(requireContext())
  4. .data(url)
  5. .addHeader() )
  6. .build() }

Will appreciate feedback, I did see a couple of post, but don't address the Jetpack part.

答案1

得分: 2

Coil没有内置支持可组合的占位符。但是您有不同的选择。

您可以使用SubcomposeAsyncImage,使用painter.state来定义不同的可组合项:

  1. SubcomposeAsyncImage(
  2. model = url,
  3. contentDescription = "contentDescription",
  4. contentScale = ContentScale.Crop,
  5. modifier = Modifier.clip(CircleShape)
  6. ) {
  7. val state = painter.state
  8. if (state is AsyncImagePainter.State.Loading || state is AsyncImagePainter.State.Error) {
  9. //text with a background circle
  10. Text(
  11. modifier = Modifier
  12. .padding(16.dp)
  13. .drawBehind {
  14. drawCircle(
  15. color = Teal200,
  16. radius = this.size.maxDimension
  17. )
  18. },
  19. text = "NG",
  20. style = TextStyle(color = Color.White, fontSize = 20.sp)
  21. )
  22. } else {
  23. SubcomposeAsyncImageContent()
  24. }
  25. }

此外,AsyncImage中的placeholder参数接受一个Painter。您可以定义自定义的TextPainter

  1. AsyncImage(
  2. model = ImageRequest.Builder(LocalContext.current)
  3. .data(url)
  4. .build(),
  5. placeholder = TextPainter(
  6. circleColor = Teal200,
  7. textMeasurer = rememberTextMeasurer(),
  8. text = "NG",
  9. circleSize = Size(200f, 200f)
  10. ),
  11. contentDescription = null,
  12. contentScale = ContentScale.Crop,
  13. modifier = Modifier.padding(16.dp)
  14. )

其中:

  1. class TextPainter(val circleColor: Color,
  2. val circleSize: Size,
  3. val textMeasurer: TextMeasurer,
  4. val text: String,
  5. ) : Painter() {
  6. val textLayoutResult: TextLayoutResult =
  7. textMeasurer.measure(
  8. text = AnnotatedString(text),
  9. style = TextStyle(color = Color.White, fontSize = 20.sp)
  10. )
  11. override val intrinsicSize: Size get() = circleSize
  12. override fun DrawScope.onDraw() {
  13. //the circle background
  14. drawCircle(
  15. color = circleColor,
  16. radius = size.maxDimension / 2
  17. )
  18. val textSize = textLayoutResult.size
  19. //The text
  20. drawText(
  21. textLayoutResult = textLayoutResult,
  22. topLeft = Offset(
  23. (this.size.width - textSize.width) / 2f,
  24. (this.size.height - textSize.height) / 2f
  25. )
  26. )
  27. }
  28. }

如何使用Jetpack Compose中的Coil制作初始图标。

英文:

Coil has no built-in support for composable placeholders.
However you have different options.

You can use the SubcomposeAsyncImage using the painter.state to define different Composables:

  1. SubcomposeAsyncImage(
  2. model = url,
  3. contentDescription = "contentDescription",
  4. contentScale = ContentScale.Crop,
  5. modifier = Modifier.clip(CircleShape)
  6. ) {
  7. val state = painter.state
  8. if (state is AsyncImagePainter.State.Loading || state is AsyncImagePainter.State.Error) {
  9. //text with a background circle
  10. Text(
  11. modifier = Modifier
  12. .padding(16.dp)
  13. .drawBehind {
  14. drawCircle(
  15. color = Teal200,
  16. radius = this.size.maxDimension
  17. )
  18. },
  19. text = "NG",
  20. style = TextStyle(color = Color.White, fontSize = 20.sp)
  21. )
  22. } else {
  23. SubcomposeAsyncImageContent()
  24. }

如何使用Jetpack Compose中的Coil制作初始图标。

Also the placeholder parameter in the AsyncImage accepts a Painter. You can define your custom TextPainter

  1. AsyncImage(
  2. model = ImageRequest.Builder(LocalContext.current)
  3. .data(url)
  4. .build(),
  5. placeholder = TextPainter(
  6. circleColor= Teal200,
  7. textMeasurer = rememberTextMeasurer(),
  8. text="NG",
  9. circleSize = Size(200f, 200f)
  10. ),
  11. contentDescription = null,
  12. contentScale = ContentScale.Crop,
  13. modifier = Modifier.padding(16.dp)
  14. )

where:

  1. class TextPainter(val circleColor: Color,
  2. val circleSize : Size,
  3. val textMeasurer: TextMeasurer,
  4. val text : String,
  5. ) : Painter() {
  6. val textLayoutResult: TextLayoutResult =
  7. textMeasurer.measure(
  8. text = AnnotatedString(text),
  9. style = TextStyle(color = Color.White, fontSize = 20.sp)
  10. )
  11. override val intrinsicSize: Size get() = circleSize
  12. override fun DrawScope.onDraw() {
  13. //the circle background
  14. drawCircle(
  15. color = circleColor,
  16. radius = size.maxDimension/2
  17. )
  18. val textSize = textLayoutResult.size
  19. //The text
  20. drawText(
  21. textLayoutResult = textLayoutResult,
  22. topLeft = Offset(
  23. (this.size.width - textSize.width) / 2f,
  24. (this.size.height - textSize.height) / 2f
  25. )
  26. )
  27. }
  28. }

答案2

得分: 0

你可以使用 Coil 的 SubcomposeAsyncImage 来实现这个功能。它允许你将任何可组合函数用作占位符或错误状态:

  1. SubcomposeAsyncImage(
  2. model = getProfileAvatar()
  3. ) {
  4. val state = painter.state
  5. if (state is AsyncImagePainter.State.Loading || state is AsyncImagePainter.State.Error) {
  6. Text(text = "NG")
  7. } else {
  8. SubcomposeAsyncImageContent()
  9. }
  10. }
英文:

You can use coil's SubcomposeAsyncImage for that. It allows you to use any composable function as a placeholder/error state:

  1. SubcomposeAsyncImage(
  2. model = getProfileAvatar()
  3. ) {
  4. val state = painter.state
  5. if (state is AsyncImagePainter.State.Loading || state is AsyncImagePainter.State.Error) {
  6. Text(text = "NG")
  7. } else {
  8. SubcomposeAsyncImageContent()
  9. }
  10. }

答案3

得分: 0

  1. val personName by remember{ mutableStateOf(String.format("%s %s", entity.firstName, entity.lastName)) }
  2. val painter = rememberAsyncImagePainter(
  3. model = ImageRequest.Builder(LocalContext.current)
  4. .allowHardware(false)
  5. .data("https://xxxx.xxxx.user_avatar.jpg")
  6. .size(Size.ORIGINAL)
  7. .build()
  8. )
  9. val isErrorState = painter.state is AsyncImagePainter.State.Error
  10. val textMeasure = rememberTextMeasurer()
  11. val textLayoutResult = textMeasure.measure(text = buildAnnotatedString { append(personName) }, style = TextStyle(color = Color.White, fontSize = 16.sp))
  12. ProfileCard(
  13. modifier = Modifier.drawBehind {
  14. if(isErrorState) {
  15. drawText(textLayoutResult = textLayoutResult)
  16. }
  17. },
  18. personName = personName,
  19. personC = entity.program ?: "",
  20. painter = rememberAsyncImagePainter(model = getProfileAvatar(entity.id)),
  21. onCardClick = {}
  22. )
英文:

Example:

  1. val personName by remember{ mutableStateOf(String.format("%s %s", entity.firstName, entity.lastName)) }
  2. val painter = rememberAsyncImagePainter(
  3. model = ImageRequest.Builder(LocalContext.current)
  4. .allowHardware(false)
  5. .data("https://xxxx.xxxx.user_avatar.jpg")
  6. .size(Size.ORIGINAL)
  7. .build()
  8. )
  9. val isErrorState = painter.state is AsyncImagePainter.State.Error
  10. val textMeasure = rememberTextMeasurer()
  11. val textLayoutResult = textMeasure.measure(text = buildAnnotatedString { append(personName) }, style = TextStyle(color = Color.White, fontSize = 16.sp))
  12. ProfileCard(
  13. modifier = Modifier.drawBehind {
  14. if(isErrorState) {
  15. drawText(textLayoutResult = textLayoutResult)
  16. }
  17. },
  18. personName = personName,
  19. personC = entity.program ?: "",
  20. painter = rememberAsyncImagePainter(model = getProfileAvatar(entity.id)),
  21. onCardClick = {}
  22. )

huangapple
  • 本文由 发表于 2023年1月9日 06:50:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051857.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定