Question

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;
    }
}
Was it helpful?

Solution

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.

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top