Android:检测软键盘RTL Vs LTR(语言方向)

时间:2015-10-05 13:15:08

标签: android android-softkeyboard

this之后,检测语言方向的方法似乎是在已经输入的文本上使用一些Java库

我有一个AutoCompleteTextView,所以我想在弹出软键盘时知道所选语言(在用户输入文本之前)。因此,当用户打开键盘语言时,我可以知道所选语言是RTL还是LTR(因此相应地改变布局)。例如,大多数使用本机RTL语言的用户都使用键盘语言和英语。

谢谢,

2 个答案:

答案 0 :(得分:3)

要在EditText获得焦点时检测键盘的语言,您可以使用以下代码段

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();
    }
}

起初,我的键盘语言是荷兰语,并打印

D/language is: nl

然后,我将我的键盘语言改为英语/美国状态并打印

D/language is: en_US

要检测语言是RTL还是LTR,您可以使用此

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;
}

这是我在https://stackoverflow.com/a/23203698/1843331

找到的RTL()方法

使用从String language

创建的区域设置来调用它
String language = getKeyboardLanguage();
boolean isRTL = isRTL(new Locale(language));

答案 1 :(得分:1)

蒂姆所写的内容基本上是正确的,但仍存在问题。在解决之前 - 为什么这个问题是重要的设计模式?假设具有原生RTL语言的用户具有双键盘(英语和他的母语)并且使用英语版本的谷歌地图等应用程序。当他想要搜索地点时 - 他的逻辑是他可能想要用他的键盘的两种语言输入地址,搜索的文本视图应该支持这个。这一切都是常见的用户行为。我们来看看Google Maps App现在的设计:

enter image description here enter image description here

正如您所看到的那样,由于软键盘语言的改变,搜索栏没有改变她的对齐方式,并且输入RTL语言并不直观。从UX的角度来看,我们需要同时监控onFocus(当键盘出现时 - 什么是开放语言)和第一个字母输入时(因为用户可能会键入键盘)。

现在我的改进使Tim的解决方案更加准确(除了添加监控首字母类型的UX)。 Tim根据预期使用母语的locale.getDisplayName()选择键盘语言。但根据Java Local documentation,当设备的默认语言环境是阿拉伯语时,所以当键盘为英语时locale.getDisplayName()会尝试用阿拉伯语打印“英语”,依此类推。所以我的解决方案基于这样的假设,即如果用户的母语是RTL(阿拉伯语或希伯来语)之一,那么他的设备默认语言环境是英语(作为最流行的语言等)或他的母语是有道理的 - 然后locale.getDisplayName()将在RTL字符中。如果这个假设不正确 - 那么我将在这里发布的相同逻辑应该应用于其他主要语言(并且学习者将检查所有受支持的Locale语言,即封闭组)。

//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();
        }
    }
}