如何判断输入法选择器是打开还是关闭?

13

我的应用程序使用 InputMethodManager.showInputMethodPicker() 打开输入法选择器(即选择键盘的菜单)。虽然我不是实际创建选择器的应用程序(而是由InputMethodManager创建的),但我知道它是一个ContextMenu,它的id是R.id.switchInputMethod

enter image description here

该选择器是多步向导的一部分,因此我需要知道选择器何时关闭,以便我的应用程序可以进行下一步。目前,我正在后台线程中检查默认键盘是否更改,但如果用户选择相同的键盘或按返回键,则无济于事。

因此,我需要一种方法来判断选择器何时关闭(或者其他巧妙的方法来知道何时进行下一步)。

提前感谢...

3个回答

17

这里有一个小技巧,请测试一下并告诉我们它是否有效。

您所需要做的就是让您的活动扩展此InputMethodActivity。当您需要用户选择输入法时,请调用pickInput(),并在用户完成后将调用 onInputMethodPicked()

package mobi.sherif.inputchangecheck;

import android.os.Bundle;
import android.os.Handler;
import android.content.Context;
import android.support.v4.app.FragmentActivity;
import android.view.inputmethod.InputMethodManager;

public abstract class InputMethodActivity extends FragmentActivity {
    protected abstract void onInputMethodPicked();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mState = NONE;
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(mState == PICKING) {
            mState = CHOSEN;
        }
        else if(mState == CHOSEN) {
            onInputMethodPicked();

        }
    }

    private static final int NONE = 0;
    private static final int PICKING = 1;
    private static final int CHOSEN = 2;
    private int mState;
    protected final void pickInput() {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showInputMethodPicker();
        mState = PICKING;
    }
}

为什么您要发布对onInputMethodPicked()的调用而不是直接调用它? - Barry Fruitman
谢谢您的回答!它是正确的,我更喜欢使用onWindowFocusChanged(),但我将赏金授予CapDroid,因为他先回答了与您基本相同的答案(检查窗口焦点)。 - Barry Fruitman
1
对我来说,这只是部分起作用。我使用 Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); 来确定我的键盘是否被选中,但是当 onInputMethodPicked 被调用时,我不认为该值已经设置。最终我在类中添加了一个 Handler,并通过 postDelaying 300ms 的实现方式,以便返回的值能够稳定下来。虽然有点 hacky,但它确实起作用了。 - Vijay Sharma
请原谅我,但是我该在哪里调用 pickInput() 函数呢?我尝试将其分配给按钮的 onclick 监听器,即通过 pickInput(); 的方式,但是它显示该方法无法解析。 - Erlend K.H.
@ErlendK.H. 您必须要扩展这个活动或者将所有方法复制粘贴到您自己的活动中。 - Behnam Maboudi

0

目前没有检查 InputMethodPicker 是否打开的机制。

但是你可以通过另一种方式进行检查,例如使用 hasWindowFocus() 方法来检查根布局是否具有焦点。

以下是示例代码:

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainlayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <Button
        android:id="@+id/btnPicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Picker" />

    <Button
        android:id="@+id/btnCheck"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop" />

</LinearLayout>

DemoappActivity.class

public class DemoappActivity extends Activity {
    /** Called when the activity is first created. */


    Button btn1 , btn2;
    InputMethodManager imeManager;

    LinearLayout mLayoutRoot;
    TimerTask timertask;
    Timer timer;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mLayoutRoot = (LinearLayout)findViewById(R.id.mainlayout);
        imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
        btn1 = (Button)findViewById(R.id.btnPicker);
        btn1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showInputMethodPicker();
            }
        });
        btn2 = (Button)findViewById(R.id.btnCheck);
        btn2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                timer.cancel();
            }
        });
        checkMyWindowHasFocus();
    }
    @Override
    protected void onDestroy() {

        timer.cancel();
        super.onDestroy();
    }

    public void checkMyWindowHasFocus()
    {
        timertask = new TimerTask() {

            @Override
            public void run() {
                System.out.println("has window focus..."+mLayoutRoot.hasWindowFocus());
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), "Has focus "+mLayoutRoot.hasWindowFocus(), Toast.LENGTH_SHORT).show();
                    }
                });
            }
        };
        timer = new Timer();
        timer.schedule(timertask, 500, 5000);

    }

    private void showInputMethodPicker() {

        if (imeManager != null) {
            imeManager.showInputMethodPicker();

        } else {
            Toast.makeText(this, "Error",Toast.LENGTH_LONG).show();
        }
    }
}

那么你的意思是,如果您的根布局没有焦点,那么这意味着 InputMethodPicker 已打开?那么其他夺取根布局焦点的情况又如何呢? - Mohammed Azharuddin Shaikh
1
这个方案运行得相当不错,但我认为Activity.onWindowFocusChanged()比后台线程更好。我仍在测试代码,很快会再次回复。谢谢。 - Barry Fruitman
非常感谢您的回答!我从来没有想过要检查窗口焦点。您的解决方案非常好(尽管我更喜欢使用onWindowFocusChanged())。 - Barry Fruitman

0

你可以使用内置函数轻松地了解它:

 @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            isMyInputMethodEnabled();// write what ever you want to do after default keyboard selected
        }


  public void isMyInputMethodEnabled() {
        String imId = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
        if (imId.contains(getPackageName())) {
            startActivity(new Intent(this, Main_uk.class));
            finish();
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接