5

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.

Uttam
  • 12,361
  • 3
  • 33
  • 30
pengwang
  • 19,536
  • 34
  • 119
  • 168

6 Answers6

13

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

Community
  • 1
  • 1
babay
  • 4,689
  • 1
  • 26
  • 40
  • how to get get content Editext container image send to server? I use : String htmlString = Html.toHtml(new SpannableString(ediites.getText())); tag image return : Sorry for English! – Do Xuan Nguyen Sep 28 '16 at 06:13
  • @babay could you help me on [this topic?](https://stackoverflow.com/q/46387217/1830228) – DolDurma Sep 24 '17 at 06:35
  • On rotation the custom edit text is opening which is not showing image. It is showing [img=1] Please help. @babay – Dheeraj D Jul 10 '20 at 11:56
  • @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. – babay Jul 20 '20 at 12:31
  • @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. – Dheeraj D Jul 21 '20 at 09:26
  • @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. – babay Jul 21 '20 at 11:59
5

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
Paresh Mayani
  • 127,700
  • 71
  • 241
  • 295
2
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

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • could you help me on [this topic](https://stackoverflow.com/questions/46387217/android-insert-image-into-edittext) ? thanks – DolDurma Sep 24 '17 at 06:48
1

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) {}
}
babay
  • 4,689
  • 1
  • 26
  • 40
1

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);
Min2
  • 10,751
  • 2
  • 19
  • 22
-1

With this,you would get the image left align and also would get cursor after the image.Try using:

mEditText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon,0, 0,0);
Hiral Vadodaria
  • 19,158
  • 5
  • 39
  • 56
  • 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 – pengwang Oct 19 '11 at 08:52
  • oh..i see. so you want to insert image as if you enter text in EditText.i don't know any way for that. – Hiral Vadodaria Oct 19 '11 at 09:06