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

Android: Detect softkeyboard RTL Vs LTR (language direction)

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

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

谢谢,

要在 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

然后,我将键盘语言更改为 English/United Stated 并打印了

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

这是我在

找到的 RTL() 方法

使用从 String language 创建的语言环境调用它:

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

Tim 写的基本正确,但还是有问题。解决方案之前——为什么这个问题是重要的设计模式?假设使用母语 RTL 语言的用户有双键盘(英语和他的母语),并在她的英语版本中使用像 Google 地图这样的应用程序。当他想搜索地点时——逻辑上他可能想用他的键盘的两种语言输入地址,并且搜索的文本视图应该支持这一点。这都是常见的用户行为。现在让我们看看Google Maps App是如何设计的:

如您所见,由于软键盘语言的变化,搜索栏没有改变对齐方式,并且以这种方式键入 RTL 语言并不直观。从用户体验的角度来看,我们需要同时监控 onFocus(当键盘 appears-what 是打开语言时)和第一个字母输入的时间(因为可能是用户更改了键盘)。

现在进行改进,使 Tim 的解决方案更加准确(除了添加监视首字母类型的 UX 之外)。 Tim 根据 locale.getDisplayName() 选择键盘语言,预计是母语。但是根据 Java Local documentation 当设备的默认区域设置为阿拉伯语时,因此当键盘为英语时 locale.getDisplayName() 将尝试用阿拉伯语打印 "English" 等等。所以我的解决方案基于这样的假设:如果用户的母语是 RTL 语言之一(阿拉伯语或希伯来语),那么他的设备默认语言环境是或英语(作为最受欢迎的语言等)或他的母语是有意义的- 然后 locale.getDisplayName() 将在 RTL 字符中。如果这个假设不正确——那么我在这里 post 的相同逻辑应该应用于其他主要语言(学究们会检查所有受支持的 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();
        }
    }
}