Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to insert drawables in text

Tags:

I want to insert small pictures, like arrow icons for example, into certain positions of contents of a TextView.

The photo below depicts exactly what I want:

this is how I want to embed icons in the text

Obviously, the most naive solution is to use multiple TextView on either side of the small ImageView objects. But this approach is not scalable.

I am curious to learn if someone has overcome this problem with some simple yet smart trick. (Maybe with help from HTML or an external library)

Any efficient solution is much appreciated.

like image 625
Behnam Avatar asked Aug 27 '14 07:08

Behnam


People also ask

How do you add Drawables?

Drag and drop your images directly onto the Resource Manager window in Android Studio. Alternatively, you can click the plus icon (+), choose Import Drawables, as shown in figure 3, and then select the files and folders that you want to import. Figure 3: Select Import Drawables from the dropdown menu.

How do you add text in drawable?

How to put text in a drawable ? Basically, you have to extend the class Drawable and set the canvas to draw the text to a drawable. As you override the draw method, it will take the canvas and draw the text on defined locations.

How do I add text to a layer-list?

One way to add Texts in your drawable layer-list is by creating a png file of the text and adding it using bitmap.

How do you cite Drawables in Android?

Note: A color resource can also be used as a drawable in XML. For example, when creating a state list drawable, you can reference a color resource for the android:drawable attribute ( android:drawable="@color/green" ).


2 Answers

You can create SpannableString and add any object to your string

TextView textView = (TextView) findViewById(R.id.textView);

ImageSpan imageSpan = new ImageSpan(this, R.drawable.ic_launcher);
SpannableString spannableString = new SpannableString(textView.getText());

int start = 3;
int end = 4;
int flag = 0;
spannableString.setSpan(imageSpan, start, end, flag);

textView.setText(spannableString);
like image 147
zapdroid Avatar answered Oct 11 '22 15:10

zapdroid


There was a similiar question a while back and someone came up with an awesome solution. I've just tweaked this one a little bit so that the image-size is always as tall as the line. So basically your icons will scale with the textSize.

Step 1 - Create a new View

Create a new Java class which extends TextView

public class TextViewWithImages extends TextView {

    public TextViewWithImages(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }
    public TextViewWithImages(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public TextViewWithImages(Context context) {
        super(context);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        Spannable s = getTextWithImages(getContext(), text, this.getLineHeight());
        super.setText(s, BufferType.SPANNABLE);
    }

    private static final Spannable.Factory spannableFactory = Spannable.Factory.getInstance();

    private static boolean addImages(Context context, Spannable spannable, float height) {
        Pattern refImg = Pattern.compile("\\Q[img src=\\E([a-zA-Z0-9_]+?)\\Q/]\\E");
        boolean hasChanges = false;

        Matcher matcher = refImg.matcher(spannable);
        while (matcher.find()) {
            boolean set = true;
            for (ImageSpan span : spannable.getSpans(matcher.start(), matcher.end(), ImageSpan.class)) {
                if (spannable.getSpanStart(span) >= matcher.start()
                        && spannable.getSpanEnd(span) <= matcher.end()
                        ) {
                    spannable.removeSpan(span);
                } else {
                    set = false;
                    break;
                }
            }
            String resName = spannable.subSequence(matcher.start(1), matcher.end(1)).toString().trim();
            int id = context.getResources().getIdentifier(resName, "drawable", context.getPackageName());
            Drawable mDrawable = context.getResources().getDrawable(id);
            mDrawable.setBounds(0, 0, (int)height, (int)height);
            if (set) {
                hasChanges = true;
                spannable.setSpan(  new ImageSpan(mDrawable),
                        matcher.start(),
                        matcher.end(),
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                );
            }
        }

        return hasChanges;
    }
    private static Spannable getTextWithImages(Context context, CharSequence text, float height) {
        Spannable spannable = spannableFactory.newSpannable(text);
        addImages(context, spannable, height);
        return spannable;
    }
}

Step 2 - Usage in layout

Now in your layout-xml just use the TextViewWithImages class

<com.stacko.examples.TextViewWithImages
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="14sp"
    android:text="@string/my_string_with_icons" />

Step 3 - Creating strings with icons

As you can see in the addImages(...) function of the TextViewWithImages class, a special pattern ([img src=my_icon/]) within the string is used in order to add the images. So here's a example:

<string name="my_string_with_icons">The [img src=ic_action_trash/] is used to delete an item while the [img src=ic_action_edit/] is to edit one.</string>

The output:

enter image description here

And as previously said it will scale with your textSize:

enter image description here

As initially said most of this post is taken from 18446744073709551615 answer here. I think this should be published as a library since it's a common use-case to have images in the text. :<

like image 25
reVerse Avatar answered Oct 11 '22 16:10

reVerse