How to disable emoji from being entered in Android EditText?
Asked Answered
U

14

51

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?

Ursi answered 10/4, 2014 at 14:23 Comment(2)
Try this: #23561186 It works on a TextView and AutoCompleteTextView.Moyer
Kotlin Solution here - https://mcmap.net/q/270329/-how-to-disable-emojis-programmatically-in-androidHomophile
A
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 !

Anastigmatic answered 3/12, 2015 at 5:55 Comment(7)
It does not compile. "Failed to resolve: com.xw.repo:xedittext:LatestVersion", any idea?Badman
Replace "LastestVersion" to version name, current is "1.0.6" (compile 'com.xw.repo:xedittext:1.0.6@aar)Anastigmatic
the Character.SURROGATE and Character.OTHER_SYMBOL were the key for me.Lodicule
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!Dehiscent
Both of them still has bug, when we type a text, then input emoji, press backspace, 2 characters will be deleted instead of 1Exaggerated
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.Nicolasanicolau
Won't this block non emoji's too? Such as Japanese/Arabic characters? Since they also use surrogatesAnneal
L
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...

Layoff answered 10/10, 2014 at 10:58 Comment(1)
This doesn't prevent user copy-paste emoji.Kite
S
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 :)

Spare answered 5/9, 2017 at 14:4 Comment(2)
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.Burble
This sometimes makes edit text behave slow, basically the letters displaying in edit text while typing has a significant lag.Cuddy
D
18

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.

Dobruja answered 8/3, 2019 at 7:41 Comment(4)
This is a great solution and seems to work great so far, THANKS! :)Hawker
Worked for me and prevented copy-paste of emoji as well.Bindweed
This is working fine able to prevent all types of emojis. Thanks.Kurtis
That's a good one , the only problem with this solution is that when the user types an Emoji it will erase all the previous typed character in the input , so instead of returning an empty string you should return the String that was typed before the user types any emojiFraktur
G
9

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() && Character.getType(it) != Character.OTHER_SYMBOL.toInt() }
    })
}

In Kotlin class:

editText.filterEmoji()

That's it. Enjoy!

Guru answered 3/6, 2021 at 10:57 Comment(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() Rositaroskes
But there is a repeating text issue while typing with this filter.Rositaroskes
this solution is working but what if particular EditText have multiple filter during that time one filter will work.Putnam
O
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.

Oversubtle answered 24/6, 2014 at 4:7 Comment(0)
H
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;
        }
    }
}
Highup answered 10/11, 2016 at 17:15 Comment(2)
Great solution, but crashes if editText has maxLength option in xml, Need to move new EmojiExcludeFilter() variable initialization to setFilters() part to avoid crash.Interior
I moved the initialization to the init() method and it works for me now.Willdon
E
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);
Enrollment answered 2/11, 2015 at 18:10 Comment(1)
This clobbers lots of valid non-english text. (eg, Japanese)Runlet
D
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);
}

}

Donetta answered 10/5, 2019 at 12:25 Comment(0)
A
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)
Anam answered 28/12, 2020 at 10:49 Comment(0)
O
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" />
Odell answered 12/2, 2021 at 19:28 Comment(0)
Z
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}"

Zsa answered 17/5, 2022 at 11:13 Comment(0)
O
-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

Odiliaodille answered 1/7, 2015 at 16:53 Comment(0)
U
-4

Try android:inputtype="textUri|textMultiLine".

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

Urethrectomy answered 24/6, 2014 at 4:1 Comment(1)
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.Oversubtle

© 2022 - 2024 — McMap. All rights reserved.