Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emoticons in EditText

I'm trying to implement an activity with an EditText that replaces some keywords with emoticons (my code is at the end).

The code works perfect except by one detail. If I type in the EditText ".sa." it is replaced by the img1, but if I want to undo it I need click 4 times the delete before the image disappear (once for each char in the key word).

Is the first time I work with Spannables and don´t know how to fix it. Can you help me?

public class MytestActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        EditText et = (EditText) findViewById(R.id.editText1);
        et.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                getSmiledText(MytestActivity.this, s);
                Log.e("",s.toString());

            }
        });
    }

    private static final HashMap<String, Integer> emoticons = new HashMap<String, Integer>();
    static {
        emoticons.put(".sa.", R.drawable.img1);
        emoticons.put(".sb.", R.drawable.img2);
    }

    public static Spannable getSmiledText(Context context, Editable builder) {

        int index;
        for (index = 0; index < builder.length(); index++) {
            for (Entry<String, Integer> entry : emoticons.entrySet()) {
                int length = entry.getKey().length();
                if (index + length > builder.length())
                    continue;
                if (builder.subSequence(index, index + length).toString().equals(entry.getKey())) {
                    builder.setSpan(new ImageSpan(context, entry.getValue()), index, index + length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    index += length - 1;
                    break;
                }
            }
        }
        return builder;
    }
}
like image 872
Addev Avatar asked Dec 09 '11 16:12

Addev


2 Answers

You could try something like this:

public void beforeTextChanged(CharSequence s, int start,
        int count, int after) {
    try {
        if (count == 1 && after == 0 &&// tried to delete a char
                s.length() >= ".sa.".length() && // string could contain an emoticon
                s.subSequence(start - ".sa.".length() + 1, start + 1).toString().equals(".sa.")// the last string is .sa.
                ) {
            et.setText(s.subSequence(0, s.length() - ".sa.".length()));
        }
    } catch (Exception e) {
    }
}

This will give another couple of problems (you will see) and it is far from being a gold solution; I only wanted to give you an idea of how to do it. Of course, you have to replace the way in which the ".sa." string is being used; I hardcoded it for the sake of simplicity.

like image 164
Cristian Avatar answered Oct 28 '22 16:10

Cristian


How about catch backspace by listener event and do it 3 times more (or remove image space maually)?

like image 23
korifey Avatar answered Oct 28 '22 16:10

korifey