Android: Detect softkeyboard RTL Vs LTR (language direction)

こ雲淡風輕ζ 提交于 2020-01-23 03:00:18

问题


Following this it seems that the way to detect language direction is to use some Java libs on the already typed text.

I have an AutoCompleteTextView so I want when the soft keyboard pops-up to know the selected language (before the user typing text). So when the user switches on the keyboard language I can know if the selected language is RTL or LTR (and therefore change layout accordingly). For example most of the users with native RTL language have keyboard with their language and English.

Thanks,


回答1:


To detect the language of the keyboard at the moment the EditText gains focus, you can use the following snippet

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText editText = (EditText) findViewById(R.id.et);
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    String language = getKeyboardLanguage();
                    Log.d("language is", language);
                }
            }
        });
    }

    private String getKeyboardLanguage() {
        InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        InputMethodSubtype inputMethodSubtype = inputMethodManager.getCurrentInputMethodSubtype();
        return inputMethodSubtype.getLocale();
    }
}

At first, my keyboard language was Dutch, and it printed

D/language is: nl

then, I changed my keyboard language to English/United Stated and it printed

D/language is: en_US

To detect whether the language is RTL or LTR, you could use this

private boolean isRTL(Locale locale) {
    final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0));
    return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
           directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
}

This isRTL() method I found at https://stackoverflow.com/a/23203698/1843331

Call that with a Locale created from the String language:

String language = getKeyboardLanguage();
boolean isRTL = isRTL(new Locale(language));



回答2:


What Tim wrote is basically correct but still there is an issue. Before the solution - why this question is important design pattern? Assume user with native RTL language has double keyboard (English and his native language) and using app like Google Maps in her English version. When he want to search for place - it's logic he might want to enter the address in both languages of his keyboard and the text view of the search should support this. This all is common user behavior. Let's take a look how Google Maps App designed now:

As you can see the search bar not changed her alignment due to soft keyboard language change, and typing such way RTL language is not intuitive. From the UX point of view We need to monitor both onFocus (when the keyboard appears-what is the opening language) and when the first letter typed (because maybe the user chaged the keyboard).

Now to my improvement to make Tim's solution more accurate (besides adding the UX of monitoring first letter type). Tim selects keyboard language according to locale.getDisplayName() which expected to be in native language. But according to Java Local documentation when the default Locale of the device is let's say Arabic, so locale.getDisplayName() when the keyboard is English will try to print "English" in Arabic and so on. So my solution is based on the assumption that if user's native language is one of the RTL's (which is Arabic or Hebrew), so it's make sense his device default Locale is or English (as the most popular language etc.) or his native language - and then locale.getDisplayName() will be in RTL chars. If this assumption is not correct - so the same logic I'll post here should be applied over other major language (and the pedants would check against all supported languages of Locale which is closed group).

//Under onCreate or etc.
textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            detectRTL();
        } else {
            changeLayoutToLTR();  //default layout is LTR...
        }
    }
});
//in order to detect RTL in first letter
textView.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

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

    @Override
    public void afterTextChanged(Editable s) {}
});

//Activity method
private void detectRTL() {
    InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    InputMethodSubtype inputMethodSubtype = inputMethodManager.getCurrentInputMethodSubtype();
    Locale mLocale = new Locale(inputMethodSubtype.getLocale());
    String localeDisplayName = mLocale.getDisplayName();
    //If the device Locale is English
    if (Locale.getDefault().getISO3Language().equals("eng")) {
        //this is how those languages displayed on English 
        if (localeDisplayName.equals("Hebrew") || localeDisplayName.equals("Arabic")) {
            changeLayoutToRTL();
        } else {
            changeLayoutToLTR();
        }
    }
    //Hidden assumption: If the device Locale isn't English - probably it's the RTL
    else {
        int directionality = Character.getDirectionality(localeDisplayName.charAt(0));  //display name of locale in it's native language...
        if (    directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
                directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC ||
                directionality == Character.DIRECTIONALITY_ARABIC_NUMBER ) {
            changeLayoutToRTL();
        } else {
            changeLayoutToLTR();
        }
    }
}


来源:https://stackoverflow.com/questions/32949611/android-detect-softkeyboard-rtl-vs-ltr-language-direction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!