how to insert image to a editText

19,436

Solution 1

Do something like this (note: you can reuse SpannableStringBuilder)

editText = (EditText)mRoot.findViewById(R.id.content);
ImageSpan imageSpan = new ImageSpan(preview);

SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(editText.getText());

// this is a string that will let you find a place, where the ImageSpan is.
String imgId = "[img=1]"; 

int selStart = editText.getSelectionStart();

// current selection is replaceв with imageId
builder.replace(editText.getSelectionStart(), editText.getSelectionEnd(), imgId);

// This adds a span to display image where the imageId is. If you do builder.toString() - the string will contain imageId where the imageSpan is.
// you can use it later - if you want to find location of imageSpan in text;
builder.setSpan(imageSpan, selStart, selStart + imgId.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(builder);

Note: See follow up answer for dealing with partial deletion of tags

Solution 2

Try this, i hope you are in search of this:

   <EditText
        android:id="@+id/editText1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:drawableLeft="@drawable/icon">
    </EditText>

The same thing you can try for:

android:drawableRight
android:drawableTop
android:drawableBottom
android:drawablePadding

Solution 3

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.text.Spannable;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.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);
        super.setText(s, BufferType.SPANNABLE);
    }

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

    private static boolean addImages(Context context, Spannable spannable) {
        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());
        if (set) {
            hasChanges = true;
            spannable.setSpan(  new ImageSpan(context, id),
                                matcher.start(),
                                matcher.end(),
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                             );
        }
    }

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

Use:

in res/layout/mylayout.xml:

            <com.xyz.customandroid.TextViewWithImages
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FFFFFF00"
                android:text="@string/can_try_again"
                android:textSize="12dip"
                style=...
                />

in res/values/strings.xml:

<string name="can_try_again">Press [img src=ok16/] to accept or [img src=retry16/] to retry</string>

where ok16.png and retry16.png are in the res/drawable/ folder

Solution 4

I guess, You'll also need some functionality for text-editing: image should be removed if one character of it is removed; this class can help (removes all the image text-placeholder if a char of it is removed)

public class ImageSpanTextWatcher implements TextWatcher {
    Object[] mTouchedSpans;
    int[] mSpanLength;
    boolean replacing = false;

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if (s instanceof SpannableStringBuilder) {
            SpannableStringBuilder ssb = (SpannableStringBuilder) s;
            mTouchedSpans = ssb.getSpans(start, start + count, ImageSpan.class);
            if (mTouchedSpans != null && mTouchedSpans.length > 0) {
                mSpanLength = new int[mTouchedSpans.length];
                for (int i = 0; i < mTouchedSpans.length; i++) {
                    mSpanLength[i] = ssb.getSpanEnd(mTouchedSpans[i]) - ssb.getSpanStart(mTouchedSpans[i]);
                }
            }
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if (s instanceof SpannableStringBuilder) {
            SpannableStringBuilder ssb = (SpannableStringBuilder) s;

            if (replacing)
                return;
            replacing = true;
            if (mTouchedSpans != null && mTouchedSpans.length > 0)
                for (int i = 0; i < mTouchedSpans.length; i++) {
                    int newLen = ssb.getSpanEnd(mTouchedSpans[i]) - ssb.getSpanStart(mTouchedSpans[i]);
                    if (newLen < mSpanLength[i]) {
                        ssb.replace(ssb.getSpanStart(mTouchedSpans[i]), ssb.getSpanEnd(mTouchedSpans[i]), "");
                    }
                }
            mTouchedSpans = null;
            mSpanLength = null;
            replacing = false;
        }
    }

    @Override
    public void afterTextChanged(Editable s) {}
}

Solution 5

I am an inserting and deleting an image in EditText by this way:

Customer button Insertion:

private void addImageInEditText(Drawable drawable) {

        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

        int selectionCursorPos = messageEditText.getSelectionStart();
        messageEditText.getText().insert(selectionCursorPos, ".");
        selectionCursorPos = messageEditText.getSelectionStart(); 
        SpannableStringBuilder builder = new SpannableStringBuilder(messageEditText.getText());
        int startPos = selectionCursorPos - ".".length();
        builder.setSpan(new ImageSpan(drawable), startPos, selectionCursorPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        messageEditText.setText(builder);
        messageEditText.setSelection(selectionCursorPos);
    }

Custom button Deletion:

private void deleteImageFromEditText() {
        String msgEditText = messageEditText.getText().toString();
        LOGE(TAG, "text length : " + msgEditText.length());
        if (msgEditText.length() > 0) {
            int selectionCursorPos = messageEditText.getSelectionStart();
            int endPosition = messageEditText.getText().length();
            LOGE(TAG, "cursor Pos: " + selectionCursorPos + " endPosition : " + endPosition);

            if (selectionCursorPos > 0) {
                int deletingObjectStartPos = selectionCursorPos - 1;
                messageEditText.getText().delete(deletingObjectStartPos, selectionCursorPos);
                messageEditText.setSelection(deletingObjectStartPos);
            }
        } else {
            messageEditText.setText("");
        }
    }

Drawable can be pass by multiple ways for testing I am doing like this:

Drawable drawable = getResources().getDrawable(R.drawable.ic_action_filter);
addImageBetweentext(drawable);
Share:
19,436
pengwang
Author by

pengwang

Updated on June 19, 2022

Comments

  • pengwang
    pengwang almost 2 years

    I want to insert a image to a editText my code is:

      CharSequence charSeq= editText.getText()+" ";
      SpannableString ss2 = new SpannableString(charSeq); 
      Drawable d2 = holder.image.getDrawable(); 
      d2.setBounds(0, 0, d2.getIntrinsicWidth(), d2.getIntrinsicHeight()); 
    
      ImageSpan span2 = new ImageSpan(d2, ImageSpan.ALIGN_BASELINE); 
      ss2.setSpan(span2,charSeq.length()-1, charSeq.length(),  
    
      Spannable.SPAN_INCLUSIVE_INCLUSIVE); 
    
      editText.setText(ss2,BufferType.SPANNABLE); 
    

    My code can run but i have some not bad experience i want to modify:

    1: You know when use ss2.setSpan() method, the image can replace the character, i only want to insert new image, donot want to the image replace the character.

    2: you know my method include "editText.getText()+" ";", i add some Extra space, so that the image can insert to the last of the CharSequence. how to not need add add some Extra, the image also insert to the last of the CharSequence.

    3.when i insert the image to the last of the CharSequence, the cursor not at the last, it appear in the front of the CharSequence. how to put the cursor at the behind the image.

    4.i want to constantly insert the image in the different of the CharSequence,how to do?

    My question so many, I want you can help me thank you very very much.

  • pengwang
    pengwang over 12 years
    you know i want to dynamic insert image,not only add a image to the text
  • pengwang
    pengwang over 12 years
    i am not only want to left align , i want to insert the imageto the text,may be in the left ,may be in the right,may be in the middle
  • Hiral Vadodaria
    Hiral Vadodaria over 12 years
    oh..i see. so you want to insert image as if you enter text in EditText.i don't know any way for that.
  • Do Xuan Nguyen
    Do Xuan Nguyen over 7 years
    how to get get content Editext container image send to server? I use : String htmlString = Html.toHtml(new SpannableString(ediites.getText())); tag image return : <img src="null"> Sorry for English!
  • DolDurma
    DolDurma over 6 years
    @babay could you help me on this topic?
  • DolDurma
    DolDurma over 6 years
    could you help me on this topic ? thanks
  • Dheeraj D
    Dheeraj D almost 4 years
    On rotation the custom edit text is opening which is not showing image. It is showing [img=1] Please help. @babay
  • babay
    babay almost 4 years
    @DheerajD 1. ensure save view state enabled (setSaveEnabled()). 2. Implement saving view state. For example, you can implement onSaveInstanceState() and onRestoreInstanceState(), save images to files and maintain connection between tags and files.
  • Dheeraj D
    Dheeraj D almost 4 years
    @babay On rotation (Landscape mode) system is opening edit text in full screen due to less space. On full screen view I am getting [img=1] . If I use android:imeOptions="flagNoExtractUi" then it Is not opening in full screen, but it is hiding inside my view (landscape mode) Can we fix this issue when we are on full screen mode. I have properly saved everything in onSavedInstance. Kindly suggest.
  • babay
    babay almost 4 years
    @DheerajD The code creates text [img=1] in your EditText and attaches ImageSpan (with image) to it. It looks like the text is persisted when you rotate screen, but ImageSpan is not. You should write some code to persist image and restore ImageSpan after screen rotated.