画像をTextViewに非同期で表示する

2022-02-28
AndroidKotlin

はじめに

非同期で画像を取得するためにGlideをCoroutineで使うのAsyncImageLorderを使います。

ロードしてからテキストを表示する

ロードしてからテキストを表示する場合は、
シンプルに画像のロードを待ってからImageSpanを入れるだけで良いと思います。
ただこれだと画像が表示されるまでテキストも表示されません。

private fun bindTextView(imageUrl: String) {
val lineHeight = binding?.textView?.lineHeight ?: return
viewLifecycleOwner.lifecycleScope.launch {
val drawable = AsyncImageLoader.load(requireContext(), imageUrl) ?: return@launch
drawable.setBounds(0, 0, lineHeight, lineHeight)
binding?.textView?.text = SpannableStringBuilder("Sample Text").also {
val fakeText = "image"
val startPosition = it.length
val imageSpan = ImageSpan(drawable)
it.append(fakeText)
it.setSpan(
imageSpan,
startPosition,
it.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}

テキストを表示してからロードする

テキストを表示してから非同期で画像を読み込む場合は、
一回画像をプレースホルダで表示して、
ロードが終わってから更新する方法がシンプルです。

fun bindTextView(imageUrl: String) {
val textView = binding?.textView ?: return
viewLifecycleOwner.lifecycleScope.launch {
asyncLoadImageWithPlaceHolder(imageUrl, textView.lineHeight) { drawable ->
textView.text = SpannableStringBuilder("Sample Text").also {
val fakeText = "image"
val startPosition = it.length
val imageSpan = ImageSpan(drawable)
it.append(fakeText)
it.setSpan(
imageSpan,
startPosition,
it.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}
}
suspend fun asyncLoadImageWithPlaceHolder(
imageUrl: String,
imageSize: Int,
drawableCallBack: (Drawable) -> Unit
) {
val placeHolderDrawable = ColorDrawable(Color.TRANSPARENT)
.also{ it.setBounds(0, 0, imageSize, imageSize) }
drawableCallBack(placeHolderDrawable)
val drawable = AsyncImageLoader.load(requireContext(), imageUrl) ?: return
drawable.setBounds(0, 0, imageSize, imageSize)
drawableCallBack(drawable)
}
© 2022 シロボタン - Context Composition