Created
March 26, 2020 19:18
-
-
Save lannyf77/6376f59f432a00fd88f40425576db233 to your computer and use it in GitHub Desktop.
iconImageGetter for TextView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.oath.doubleplay.utils | |
import android.content.res.Resources | |
import android.graphics.Bitmap | |
import android.graphics.Canvas | |
import android.graphics.drawable.BitmapDrawable | |
import android.graphics.drawable.Drawable | |
import android.text.Html.ImageGetter | |
import android.util.Log | |
import android.widget.TextView | |
import com.bumptech.glide.Glide | |
import com.bumptech.glide.load.engine.DiskCacheStrategy | |
import com.bumptech.glide.request.Request | |
import com.bumptech.glide.request.RequestOptions | |
import com.bumptech.glide.request.target.SizeReadyCallback | |
import com.bumptech.glide.request.target.Target | |
import com.bumptech.glide.request.transition.Transition | |
import com.oath.doubleplay.stream.view.holder.CheckTweetId | |
import kotlinx.coroutines.CoroutineScope | |
import kotlinx.coroutines.Dispatchers | |
import kotlinx.coroutines.launch | |
import java.lang.ref.WeakReference | |
class TextViewIconGetter(textView: TextView, iconSizeInDp: Int, val sourceId: String, val iconReadyListener: OnIconAvailableListener?) : ImageGetter { | |
private val textViewRef: WeakReference<TextView> = WeakReference(textView) | |
private val iconSize: Int = (iconSizeInDp * Resources.getSystem().displayMetrics.density).toInt() | |
/** | |
* interface for being notified that a new icon drawable is available. | |
* The onIconAvailable is called when icon drawable is ready | |
*/ | |
interface OnIconAvailableListener { | |
val owner: WeakReference<CheckTweetId> // owner can check if the data is for it, abstract | |
/** | |
* @param drawable a drawable or null | |
* @param textViewRef the textView the drawable is with | |
*/ | |
fun onImageAvailable(drawable: Drawable?, sourceId: String, textViewRef: WeakReference<TextView>) | |
} | |
override fun getDrawable(source: String): Drawable? { | |
return textViewRef.get()?.let { txtView -> | |
val drawable = BitmapDrawablePlaceholder(txtView, iconSize, sourceId, iconReadyListener) | |
CoroutineScope(Dispatchers.IO).launch { | |
val requestOptions = RequestOptions() | |
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) | |
.override(iconSize, iconSize) // resize does not respect aspect ratio | |
Glide.with(textViewRef.get()!!.context) | |
.asBitmap() | |
.apply(requestOptions) | |
.load(source) | |
.into(drawable) | |
} | |
drawable | |
} | |
} | |
private class BitmapDrawablePlaceholder internal constructor(textView: TextView, | |
private val iconSize: Int, | |
private val sourceId: String, | |
private val iconReadyListener: OnIconAvailableListener? | |
) : BitmapDrawable(textView.resources, Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888)), Target<Bitmap> { | |
val textViewRef: WeakReference<TextView> = WeakReference(textView) | |
private var drawable: Drawable? = null | |
override fun draw(canvas: Canvas) { | |
if (drawable != null) { | |
drawable!!.draw(canvas) | |
} | |
} | |
private fun onDrawableReady(drawable: Drawable) { | |
try { | |
iconReadyListener?.let { listener -> | |
this.drawable = drawable | |
drawable.setBounds(0, 0, iconSize, iconSize) | |
setBounds(0, 0, iconSize, iconSize) | |
listener.onImageAvailable(this.drawable, sourceId, textViewRef) | |
} | |
} catch (ex: Throwable) { | |
Log.e("+++", "+++ !!! exception in onDrawableReady($ex)", ex) | |
} | |
} | |
override fun onLoadStarted(placeholderDrawable: Drawable?) { | |
placeholderDrawable?.let { onDrawableReady(it) } | |
} | |
override fun onLoadFailed(errorDrawable: Drawable?) { | |
Log.d("+++", "+++ onLoadStarted(), Drawable:$errorDrawable") | |
errorDrawable?.let { onDrawableReady(it) } | |
} | |
override fun onResourceReady(bitmap: Bitmap, transition: Transition<in Bitmap>?) { | |
onDrawableReady(BitmapDrawable(textViewRef.get()?.resources ?: Resources.getSystem(), bitmap)) | |
} | |
override fun onLoadCleared(placeholderDrawable: Drawable?) { | |
placeholderDrawable?.let { onDrawableReady(it) } | |
} | |
override fun getSize(cb: SizeReadyCallback) { | |
cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) | |
} | |
override fun removeCallback(cb: SizeReadyCallback) {} | |
var cachedRequest: Request? = null | |
override fun setRequest(request: Request?) { | |
cachedRequest = request | |
} | |
override fun getRequest(): Request? { | |
return request | |
} | |
override fun onStart() {} | |
override fun onStop() {} | |
override fun onDestroy() {} | |
} | |
init { | |
Log.i("+++", "+++ TextViewIconGetter(), this:$this") | |
} | |
} | |
/** | |
* when icon is ready, make sure this listener is for the owner of the tweet and update the textView | |
*/ | |
class IconReadyListener(override val owner: WeakReference<CheckTweetId>) : TextViewIconGetter.OnIconAvailableListener { | |
override fun onImageAvailable(drawable: Drawable?, sourceId: String, textViewRef: WeakReference<TextView>) { | |
CoroutineScope(Dispatchers.Main).launch { | |
try { | |
owner.get()?.let { tweetOwner -> | |
if (tweetOwner.isSameTweet(sourceId)) { | |
textViewRef.get()?.let { | |
it.text = it.text | |
} | |
} | |
} | |
} catch (ex: Throwable) { | |
Log.d("+++", "+++ !!! exception in onImageAvailable($ex)", ex) | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment