49

Most implementations of the text inputType (other than URI, password, etc.) for EditText and TextView allow Emoji - although in most Google keyboard configurations this button is hidden. Is there a way to disable Emoji from being entered in an EditText? Is there an inputType parameter that could be paired with textMultiLine that would disable Emoji?

Alex Wang
  • 998
  • 1
  • 9
  • 13
  • Try this: http://stackoverflow.com/questions/23560686/programmatically-hide-disable-emoticons-on-android-soft-keyboard/39491095#39491095 It works on a TextView and AutoCompleteTextView. – user1506104 Sep 14 '16 at 13:34
  • Kotlin Solution here - https://stackoverflow.com/a/52947835/3333878 – abitcode Oct 23 '18 at 11:32

14 Answers14

29

Modify build.gradle file, add XEditText to your project:

dependencies{
    compile 'com.xw.repo:xedittext:2.0.0@aar'
}

after that, in your layout.xml:

<com.xw.repo.XEditText
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:x_disableEmoji="true"/>

Or:

Customize EditText like this:

public class CustomEditText extends EditText {
    public CustomEditText(Context context) {
        super(context);
        init();
    }

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

    public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setFilters(new InputFilter[]{new EmojiExcludeFilter()});
    }

    private class EmojiExcludeFilter implements InputFilter {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            for (int i = start; i < end; i++) {
                int type = Character.getType(source.charAt(i));
                if (type == Character.SURROGATE || type == Character.OTHER_SYMBOL) {
                    return "";
                }
            }
            return null;
        }
    }
}

Both will work well !

woxingxiao
  • 963
  • 9
  • 13
  • It does not compile. "Failed to resolve: com.xw.repo:xedittext:LatestVersion", any idea? – horro Dec 30 '15 at 17:16
  • Replace "LastestVersion" to version name, current is "1.0.6" (compile 'com.xw.repo:xedittext:1.0.6@aar) – woxingxiao Jun 12 '16 at 06:22
  • the `Character.SURROGATE` and `Character.OTHER_SYMBOL` were the key for me. – annapetry Jan 06 '17 at 05:04
  • 9
    The answer here should be the latter. you cannot suggest developers to use a third party libs for this kind of problem really. In android, such a small problem requires external libs to be fixed. This getting out of hand. SAD! – Neon Warge May 12 '17 at 01:40
  • 1
    Both of them still has bug, when we type a text, then input emoji, press backspace, 2 characters will be deleted instead of 1 – HendraWD Jun 08 '17 at 17:34
  • This doesn't allow symbols that I want to accept such as degree signs. Changing to just return "" on type == Character.SURROGATE (remove the OTHER) results in some emojis still being allowed which is also not acceptable. – Mira_Cole Dec 19 '18 at 20:57
  • 1
    Won't this block non emoji's too? Such as Japanese/Arabic characters? Since they also use surrogates – behelit Jan 19 '20 at 23:16
23

There is tricky way for disabling emoji from keyboard..

you just have to set

android:inputType="textEmailAddress"

for EditText..

  <EditText
    android:id="@+id/edt_note"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/note"
    android:inputType="textEmailAddress"
    android:padding="10dp"
    android:textColor="@color/white" />

I am not sure that it will work in all cases but in my case it worked for me...

Pragnesh Ghoda シ
  • 8,318
  • 3
  • 25
  • 40
23

There is value digits available in xml file for EditText. You can set there all acceptable chars.

<EditText
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:digits="qwertyuiopasdfghjklzxcvbnm 1234567890 QWERTYUIOPASDFGHJKLZXCVBNM" />

I know, it's not the best solution but works :)

Adrian Grygutis
  • 470
  • 1
  • 8
  • 18
  • 6
    This is a great solution if your building an English only app. But I can't imagine doing this for every single language I want my app localised too. – Slobodan Antonijević Jul 11 '19 at 08:53
  • 1
    This sometimes makes edit text behave slow, basically the letters displaying in edit text while typing has a significant lag. – Samrat Dec 24 '19 at 17:41
15

Add this emoji filter class:

public class EmojiFilter {
    public static InputFilter[] getFilter()
    {
         InputFilter EMOJI_FILTER = new InputFilter() {

            @Override
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                for (int index = start; index < end; index++) {

                    int type = Character.getType(source.charAt(index));

                    if (type == Character.SURROGATE || type==Character.NON_SPACING_MARK
                            || type==Character.OTHER_SYMBOL) {
                        return "";
                    }
                }
                return null;
            }
        };
         return new InputFilter[]{EMOJI_FILTER};
    }
}

And to disable emoji in edit text, do this:

editText.setFilters(EmojiFilter.getFilter());

There were some emoji which were able to type so i added:

type==Character.NON_SPACING_MARK || type==Character.OTHER_SYMBOL

in the if condition.

Suraj Vaishnav
  • 7,777
  • 4
  • 43
  • 46
7

There is nothing that will 100% disable emoji. The keyboard can act to any mode it sees in whatever way it thinks best, so there is no setting that will prevent emoji. If you must prevent it, do it by white or blacklisting characters with a TextWatcher.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
7

Code from @woxingxiao works great, until you specify any inputType in your xml, for example android:inputType="textMultiLine".

I changed a little bit his proposal and I think it works great.

public class EmojiExcludeEditText extends EditText {

    private EmojiExcludeFilter emojiExcludeFilter;

    public EmojiExcludeEditText(Context context) {
        super(context);
        init();
    }

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

    public EmojiExcludeEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        if (emojiExcludeFilter == null) {
            emojiExcludeFilter = new EmojiExcludeFilter();
        }
        setFilters(new InputFilter[]{emojiExcludeFilter});
    }

    @Override
    public void setFilters(InputFilter[] filters) {
        if (filters.length != 0) { //if length == 0 it will here return when init() is called
            boolean add = true;
            for (InputFilter inputFilter : filters) {
                if (inputFilter == emojiExcludeFilter) {
                    add = false;
                    break;
                }
            }
            if (add) {
                filters = Arrays.copyOf(filters, filters.length + 1);
                filters[filters.length - 1] = emojiExcludeFilter;
            }
        }
        super.setFilters(filters);
    }

    private class EmojiExcludeFilter implements InputFilter {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            for (int i = start; i < end; i++) {
                int type = Character.getType(source.charAt(i));
                if (type == Character.SURROGATE || type == Character.OTHER_SYMBOL) {
                    return "";
                }
            }
            return null;
        }
    }
}
lbenedetto
  • 2,022
  • 1
  • 21
  • 39
pauminku
  • 3,526
  • 3
  • 22
  • 24
  • 1
    Great solution, but crashes if editText has maxLength option in xml, Need to move new EmojiExcludeFilter() variable initialization to setFilters() part to avoid crash. – Jonas Dec 19 '17 at 16:29
  • I moved the initialization to the init() method and it works for me now. – lbenedetto Oct 19 '18 at 18:57
6

You can write input filter for blacklist/whitelist characters

public static InputFilter getEditTextFilterEmoji()
{
    return new InputFilter()
    {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
        {
            CharSequence sourceOriginal = source;
            source = replaceEmoji(source);
            end = source.toString().length();

            if (end == 0) return ""; //Return empty string if the input character is already removed

            if (! sourceOriginal.toString().equals(source.toString()))
            {
                char[] v = new char[end - start];
                TextUtils.getChars(source, start, end, v, 0);

                String s = new String(v);

                if (source instanceof Spanned)
                {
                    SpannableString sp = new SpannableString(s);
                    TextUtils.copySpansFrom((Spanned) source, start, end, null, sp, 0);
                    return sp;
                }
                else
                {
                    return s;
                }
            }
            else
            {
                return null; // keep original
            }
        }

        private String replaceEmoji(CharSequence source)
        {

            String notAllowedCharactersRegex = "[^a-zA-Z0-9@#\\$%\\&\\-\\+\\(\\)\\*;:!\\?\\~`£\\{\\}\\[\\]=\\.,_/\\\\\\s'\\\"<>\\^\\|÷×]";
            return source.toString()
                    .replaceAll(notAllowedCharactersRegex, "");
        }

    };
}

Then set it as EditText filters;

InputFilter[] filterArray = new InputFilter[] {getEditTextFilterEmoji()}
editText.setFilters(filterArray);
erandac
  • 575
  • 5
  • 8
6

I have made Kotlin Extension for this purpose. It will also prevent copy paste of Emoji.

Extension:

fun EditText.filterEmoji() {
    filters = arrayOf(InputFilter { source, _, _, _, _, _ ->
        source.filter { Character.getType(it) != Character.SURROGATE.toInt() }
    })
}

In Kotlin class:

editText.filterEmoji()

That's it. Enjoy!

Muhammad Umair Shafique
  • 2,475
  • 1
  • 30
  • 39
  • 3
    Still, it is allowing some of the symbols. To avoid those as well do the following inside the filter: `Character.getType(it) != Character.SURROGATE.toInt() && Character.getType(it) != Character.OTHER_SYMBOL.toInt() ` – Shailendra Madda Nov 30 '21 at 05:59
  • But there is a repeating text issue while typing with this filter. – Shailendra Madda Dec 11 '21 at 06:44
1

You can use input filter for removing un-wanted characters, Here I used ascci values for filtering.

public class CustomEditText extends AppCompatEditText {
private InputFilter unwantedCharacterFilter;

public CustomEditText(Context context) {
    super(context);
}

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

public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

private void init() {
    setFilters(new InputFilter[]{});
}
private InputFilter getUnwantedCharacterFilter() {
    if (null == unwantedCharacterFilter) {
        unwantedCharacterFilter = new InputFilter() {
            @Override
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                if (!TextUtils.isEmpty(source)) {
                    for (int index = start; index < end; index++) {
                        if (source.charAt(index) < 0 || source.charAt(index) > 177) {
                            return "";
                        }
                    }
                }
                return null;
            }
        };
    }
    return unwantedCharacterFilter;
}

@Override
public void setFilters(InputFilter[] filters) {
    List<InputFilter> filterList = new ArrayList<>(Arrays.asList(filters));
    filterList.add(getUnwantedCharacterFilter());
    InputFilter specifiedFilters[] = filterList.toArray(new InputFilter[]{});
    super.setFilters(specifiedFilters);
}

}

user2851150
  • 397
  • 5
  • 12
1

Emoji use area of Unicode with a range of code points from U+1F604 to U+1F539. And Character.SURROGATE reserved the range is over the Emoji’s.

val EMOJI_FILTER =InputFilter { source, start, end, dest, dstart, dend ->
                for (index in start until end) {
                    val type = Character.getType(source[index])
                    if (type == Character.SURROGATE.toInt()) {
                        return@InputFilter ""
                    }
                }
                null
            }


        etLintEdt.filters = arrayOf(EMOJI_FILTER)
Prasann
  • 71
  • 4
0

You can use input type as "textVisiblePassword". This will disable emojis from keyboard. However user can still copy-paste the smileys into the edit text.

<EditText
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:inputType="textVisiblePassword" />
Akash Dubey
  • 327
  • 4
  • 5
0
fun EditText.filterEmoji() {
    filters = arrayOf(
        InputFilter { source, _, _, _, _, _ ->
            source.filter {
                Character.getType(it) != Character.SURROGATE.toInt() && Character.getType(it) != Character.OTHER_SYMBOL.toInt()
            }
        }
    )
}

For kotlin ,
use BindingAdapter
@BindingAdapter("disableEmoji")
fun bindDisableEmoji(view: EditText, disableEmoji: Boolean) {
    if (disableEmoji) {
        view.filterEmoji()
    }
}

in xml app:disableEmoji="@{true}"

Mechadroid
  • 17
  • 3
-2

Another solution:

mEtMessageText.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);

In this example it shows the ENTER button

InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS is equivalent to android:inputType="textEmailAddress" in XML layout

-4

Try android:inputtype="textUri|textMultiLine".

In this parameter, the keyboard will change the voice input button to '/' button.

  • 3
    Not all keyboards will do that. Some keyboard might, but it is far from a universal feature. You can't depend on a keyboard doing any specific behavior to a mode. – Gabe Sechan Jun 24 '14 at 04:05