1

Is that possible to add a custom view into a spannable text?

In android.text.style package I can see many types of spannable objects, but I wonder if I can add a custom view.

Sort of spanable.setSpan(CustomView, .. , .. ,..)

Note that: CustomView maybe any sort of view i.e: WebView

Ibrahim Ali
  • 1,237
  • 9
  • 20
  • The question should be if it is advisable to add a view as reference to a `Spannable`. Since a view contains a context and the spannable string is not bound to any lifecycle, you should not put the reference there. – tynn Sep 17 '20 at 08:43
  • @tynn you're right regarding to view's context/lifecycle?...BUT what about saving references in WeakHashMap and destroy them once I left the `SpannableText` MainView.? SO my question still exist... is that possible to inject custom-view into the spanabble text? – Ibrahim Ali Sep 17 '20 at 09:41
  • Do you simply want the custom view to appear within the text as an image? This would be as it would appear in a _ViewGroup_ but fitting within the text bounds? Would you want the custom view to be operational beyond its display, i.e., be clickable, accept focus, be editable, etc. – Cheticamp Sep 17 '20 at 16:00
  • @Cheticamp I think the custom view cannot come with beyond display attributes.. while I can handle clicks like I did with ` – Ibrahim Ali Sep 17 '20 at 16:28
  • 2
    An _ImageSpan_ will display an image within the text but you will need a bitmap or some kind of drawable from your custom view. If an _ImageSpan_ works, does your question reduce to how to get a bitmap or something that can be used for the _ImageSpan_ from the custom view? (I don't think that wonsuc's answer is too far afield. I question the statement about _ViewGroups_ but, as far as I can tell, @wonsuc's answer is not about animations.) – Cheticamp Sep 17 '20 at 17:28
  • @Cheticamp Please feel free to post an answer : ) – Ibrahim Ali Sep 18 '20 at 20:21

2 Answers2

1

In Android, only ViewGroup class can contain another view, therefore it's much proper to say,

Is that possible to add a spannable text into a custom view?

Then the answer is Yes, if your custom view extends ViewGroup class.

However, if you want to draw specific graphics or animations with spannable, you would need to draw on the Canvas directly from your custom view.

For examples, if you check DynamicDrawableSpan class in android.text.style package.

@Override
public void draw(@NonNull Canvas canvas, CharSequence text,
        @IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,
        int top, int y, int bottom, @NonNull Paint paint) {
    Drawable b = getCachedDrawable();
    canvas.save();

    int transY = bottom - b.getBounds().bottom;
    if (mVerticalAlignment == ALIGN_BASELINE) {
        transY -= paint.getFontMetricsInt().descent;
    } else if (mVerticalAlignment == ALIGN_CENTER) {
        transY = (bottom - top) / 2 - b.getBounds().height() / 2;
    }

    canvas.translate(x, transY);
    b.draw(canvas);
    canvas.restore();
}

It has draw method which draw the Drawable on the Canvas directly, this code will be good start if you want to create custom spannable class which displays various things more than existing SDK classes.

wonsuc
  • 3,498
  • 1
  • 27
  • 30
0

So looks like it will be challenging to use Spannable way to handle such case.

Therefore I created a new library to handle tags so I can use them wherever I want.

And here is an example

HtmlParser.Builder(StringSource(source)).setCallback(object : HtmlParser.ParserCallbacks {
override fun onParseFinished(list: List<Element>) {
list.forEach {
        Log.d(TAG, "onParseFinished: ${ElementType.values()[it.type]} ||| ${it.toString()}")
    if (it is ImageElement) {
        Log.d(TAG, "onImageFound: $it ||| ${it.ImageUrl}")
    } else if (it is IFrameElement) {
        Log.d(TAG, "onIFrameFound: $it ||| ${it.url}")
    } else if (it is BlockQuoteElement) {
        Log.d(TAG, "onBlockQuoteFound: ${it.data} ${it.text}")
    } else if (it is FigureElement) {
        Log.d(TAG, "onFigure: ${it.caption}  ${it.url}")
    }
 } 
 } override fun onParseError(exception: Exception) {}})
   .build()

Now I can handle elements in whatever I want i.e: RecycleView

Ibrahim Ali
  • 1,237
  • 9
  • 20