I'm facing an issue with HtmlTextView, when an image tag is present in response body, textview is not resizing to show the contents.
P.S - On Reopening the same screen, textview is displayed correctly. Does not work only when open for the first time.
Please see the attached code for ImageGetter below,
package com.desidime.editor.editor.render
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.View
import android.widget.TextView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.request.transition.Transition
import com.desidime.editor.editor.Constants
import com.desidime.editor.editor.Constants.dp2px
import com.desidime.editor.editor.inner.Html
import java.lang.ref.WeakReference
class AreImageGetter(private val container: TextView) : Html.ImageGetter {
override fun getDrawable(source: String): Drawable {
val urlDrawable = UrlDrawable()
val target = ImageGetterTarget(urlDrawable, this, container, true, Constants.isEmoji(source),
Constants.SCREEN_WIDTH)
Glide.with(container.context)
.asDrawable()
.load(source)
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL))
.into(target)
return urlDrawable
}
private class ImageGetterTarget(urlDrawable: UrlDrawable,
imageGetter: AreImageGetter,
container: View,
private val matchParentWidth: Boolean,
private val isEmoji: Boolean,
maxWidth: Int) : SimpleTarget<Drawable>(maxWidth, Target.SIZE_ORIGINAL) {
private val drawableReference: WeakReference<UrlDrawable> = WeakReference(urlDrawable)
private val imageGetterReference: WeakReference<AreImageGetter> = WeakReference(imageGetter)
private val containerReference: WeakReference<View> = WeakReference(container)
private var scale: Float = 1f
private fun getScale(drawable: Drawable): Float {
val container = containerReference.get()
if (!matchParentWidth || container == null) {
return 1f
}
val maxWidth = container.width.toFloat() - container.paddingLeft - container.paddingRight
val originalDrawableWidth = drawable.intrinsicWidth.toFloat()
println(
"/*-------------------------------------------------------------------------------------------*/")
println("maxWidth : $maxWidth")
println("container.width.toFloat() : ${container.width.toFloat()}")
println("container.paddingLeft : ${container.paddingLeft}")
println("container.paddingRight : ${container.paddingRight}")
println("originalDrawableWidth : $originalDrawableWidth")
println("drawable.intrinsicWidth.toFloat() : ${drawable.intrinsicWidth.toFloat()}")
return maxWidth / originalDrawableWidth
}
override fun onResourceReady(drawable: Drawable, transition: Transition<in Drawable>?) {
val urlDrawable = drawableReference.get() ?: return
if (isEmoji) {
if (containerReference.get() != null) {
val dp2px = dp2px(containerReference.get()?.context, 24f)
drawable.setBounds(0, 0, dp2px, dp2px)
urlDrawable.setBounds(0, 0, drawable.bounds.right, drawable.bounds.bottom)
}
} else {
scale = getScale(drawable)
val width: Int = drawable.intrinsicWidth
val height: Int = drawable.intrinsicHeight
println("(drawable.intrinsicWidth * scale).toInt() ${(drawable.intrinsicWidth * scale).toInt()}")
println("(drawable.intrinsicHeight * scale).toInt() ${(drawable.intrinsicHeight * scale).toInt()}")
println("(drawable.intrinsicHeight)${(drawable.intrinsicHeight)}")
println("(drawable.intrinsicWidth)${(drawable.intrinsicWidth)}")
drawable.setBounds(0, 0, (drawable.intrinsicWidth * scale).toInt(),
(drawable.intrinsicHeight * scale).toInt())
// drawable.setBounds(0, 0, width, height)
// set the correct bound according to the result from HTTP call
urlDrawable.setBounds(0, 0, (drawable.intrinsicWidth * scale).toInt(),
(drawable.intrinsicHeight * scale).toInt())
// urlDrawable.setBounds(0, 0, width, height)
}
// change the reference of the current drawable to the result from the HTTP call
urlDrawable.drawable = drawable
val imageGetter = imageGetterReference.get() ?: return
// redraw the image by invalidating the container
imageGetter.container.invalidate()
// re-set text to fix images overlapping text
imageGetter.container.text = imageGetter.container.text
println(
"/*-------------------------------------------------------------------------------------------*/")
}
}
inner class UrlDrawable : BitmapDrawable() {
var drawable: Drawable? = null
override fun draw(canvas: Canvas) {
// override the draw to facilitate refresh function later
try {
if (drawable != null) {
drawable!!.draw(canvas)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
Code for image tag
private static void startImg(Editable text, Attributes attributes, Html.ImageGetter img) {
String src = attributes.getValue("", "src");
if (src == null) {
return;
}
Drawable d = null;
ImageSpan imageSpan = null;
if (img != null) {
Log.e("HTML", "startImg");
d = img.getDrawable(src);
imageSpan = new AreImageSpan(sContext, d, src);
}
if (d == null) {
if (sContext == null) {
d = Resources.getSystem().getDrawable(R.drawable.ic_image);
} else {
d = sContext.getResources().getDrawable(R.drawable.ic_image);
}
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
}
Log.e("HTML", imageSpan.getSource());
int len = text.length();
text.append('\uFFFC');
text.setSpan(imageSpan, len, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
Update
Just Found out
d = img.getDrawable(src);
This Line return image with bounds Rect(0, 0 - 0, 0) on first open.