304

ソフトウェア(別名「ソフト」)キーボードが画面に表示されているかどうかをAndroidで検出する方法はありますか?

4

34 に答える 34

309

これは私にとってはうまくいきます。おそらく、これはすべてのバージョンで常に最良の方法です

onGlobalLayout メソッドが何度も呼び出されるため、キーボードの可視性のプロパティを作成し、この変更の遅延を観察すると効果的です。また、デバイスの回転を確認するのは良いことでwindowSoftInputModeはありませんadjustNothing

boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
    print("keyboard " + opened);
}

// ContentView is the root view of the layout of this activity/fragment    
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

        Rect r = new Rect();
        contentView.getWindowVisibleDisplayFrame(r);
        int screenHeight = contentView.getRootView().getHeight();

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        int keypadHeight = screenHeight - r.bottom;

        Log.d(TAG, "keypadHeight = " + keypadHeight);

        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true
                onKeyboardVisibilityChanged(true)
            }
        }
        else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false
                onKeyboardVisibilityChanged(false)
            }
        }
    }
});
于 2014-11-17T01:06:17.373 に答える
79

これを試して:

InputMethodManager imm = (InputMethodManager) getActivity()
            .getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }
于 2011-09-23T14:10:30.333 に答える
73

これに使用できる単純なクラスを作成しました: https://github.com/ravindu1024/android-keyboardlistener。プロジェクトにコピーして、次のように使用するだけです。

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});
于 2016-07-15T02:37:01.523 に答える
32

非常に簡単

1. ルート ビューに id を追加します。

rootViewこの場合、私のルートビューを指しているビューにすぎませんrelative layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/addresses_confirm_root_view"
                android:background="@color/WHITE_CLR">

2. アクティビティでルート ビューを初期化します。

RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);

3. を使用して、キーボードが開いているか閉じているかを検出しますgetViewTreeObserver()

    rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();
                
                if (heightDiff > 100) { // Value should be less than keyboard's height 
                    Log.e("MyActivity", "keyboard opened");
                } else { 
                    Log.e("MyActivity", "keyboard closed");
                }
            }
        });
于 2016-02-11T19:11:37.470 に答える
13

AccessibilityServices、ウィンドウのインセット、画面の高さの検出などで長い間遊んだ後、これを行う方法を見つけたと思います。

免責事項: Android では隠しメソッドを使用しているため、一貫性がない可能性があります。しかし、私のテストでは、うまくいくようです。

メソッドはInputMethodManager#getInputMethodWindowVisibleHeight()で、Lollipop (5.0) から存在しています。

現在のキーボードの高さ (ピクセル単位) を返す呼び出し。理論的には、キーボードの高さを 0 ピクセルにするべきではないため、(Kotlin で) 簡単な高さチェックを行いました。

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
    //keyboard is shown
else {
    //keyboard is hidden
}

隠しメソッドを呼び出すときにリフレクションを回避するためにAndroid Hidden APIを使用します (私が開発したアプリでは、ほとんどがハッキー/チューナー アプリです) が、これはリフレクションでも可能である必要があります。

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
val height = windowHeightMethod.invoke(imm) as Int
//use the height val in your logic
于 2018-09-04T18:09:19.467 に答える
8

これを基礎として使用しました:https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android

/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
     public int result = -1;
     public IMMResult() {
         super(null);
}

@Override 
public void onReceiveResult(int r, Bundle data) {
    result = r;
}

// poll result value for up to 500 milliseconds
public int getResult() {
    try {
        int sleep = 0;
        while (result == -1 && sleep < 500) {
            Thread.sleep(100);
            sleep += 100;
        }
    } catch (InterruptedException e) {
        Log.e("IMMResult", e.getMessage());
    }
    return result;
}
}

次に、このメソッドを書きました:

public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {
    
    IMMResult result = new IMMResult();
    int res;
    
    imm.showSoftInput(v, 0, result);

    // if keyboard doesn't change, handle the keypress
    res = result.getResult();
    if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
            res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {

        return true;
    }
    else
        return false;

}

次に、これを使用して、ソフトキーボードを開いた可能性のあるすべてのフィールド (EditText、AutoCompleteTextView など) をテストできます。

    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
        //close the softkeyboard
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

もちろん、理想的なソリューションではありませんが、仕事は完了します。

于 2015-06-27T15:38:46.307 に答える
7

showSoftInput() および hideSoftInput() のコールバック結果を使用して、キーボードのステータスを確認できます。詳細とサンプル コードは次の URL にあります。

https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android

于 2012-02-20T23:45:04.060 に答える
6

これは、私が必要とする要件に対してはるかに複雑ではありませんでした。これが役立つことを願っています:

MainActivity で:

public void dismissKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0);
    mKeyboardStatus = false;
}

public void showKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    mKeyboardStatus = true;
}

private boolean isKeyboardActive(){
    return mKeyboardStatus;
}

mKeyboardStatus のデフォルトのプリミティブ ブール値はfalseに初期化されます。

次に、次のように値を確認し、必要に応じてアクションを実行します。

 mSearchBox.requestFocus();
    if(!isKeyboardActive()){
        showKeyboard();
    }else{
        dismissKeyboard();
    }
于 2015-08-26T18:25:07.543 に答える
6

この回答を参照できます- https://stackoverflow.com/a/24105062/3629912

それはいつも私のために働いた。

adb shell dumpsys window InputMethod | grep "mHasSurface"

ソフトウェア キーボードが表示されている場合は true を返します。

于 2014-09-11T07:50:23.437 に答える
4

次のように、GlobalLayoutListener を設定してこれを行いました。

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightView = activityRootView.getHeight();
                int widthView = activityRootView.getWidth();
                if (1.0 * widthView / heightView > 3) {
                    //Make changes for Keyboard not visible
                } else {
                    //Make changes for keyboard visible
                }
            }
        });
于 2014-02-21T21:59:09.267 に答える
3

このコードを試してみてください。KeyboardShown が Shown の場合、この関数は真の値を返します....

private final String TAG = "TextEditor";
private TextView mTextEditor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_editor);
    mTextEditor = (TextView) findViewById(R.id.text_editor);
    mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            isKeyboardShown(mTextEditor.getRootView());
        }
    });
}

private boolean isKeyboardShown(View rootView) {
    /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
    final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;

    Rect r = new Rect();
    rootView.getWindowVisibleDisplayFrame(r);
    DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
    /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
    int heightDiff = rootView.getBottom() - r.bottom;
    /* Threshold size: dp to pixels, multiply with display density */
    boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;

    Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
            + "root view height:" + rootView.getHeight() + ", rect:" + r);

    return isKeyboardShown;
}
于 2015-06-11T14:25:53.093 に答える
1

Android では、ADB シェルを介して検出できます。私はこの方法を書いて使用しています:

{
        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession("<userName>", "<IP>", 22);
            session.setPassword("<Password>");
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            ChannelExec channel = (ChannelExec)session.openChannel("exec");
            BufferedReader in = new BufferedReader(new    
            InputStreamReader(channel.getInputStream()));
            channel.setCommand("C:/Android/android-sdk/platform-tools/adb shell dumpsys window 
            InputMethod | findstr \"mHasSurface\"");
            channel.connect();

            String msg = null;
            String msg2 = " mHasSurface=true";

            while ((msg = in.readLine()) != null) {
                Boolean isContain = msg.contains(msg2);
                log.info(isContain);
                if (isContain){
                    log.info("Hiding keyboard...");
                    driver.hideKeyboard();
                }
                else {
                    log.info("No need to hide keyboard.");
                }
            }

            channel.disconnect();
            session.disconnect();

        } catch (JSchException | IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
于 2015-08-03T11:44:40.750 に答える
0

ソフトキーボードが表示されているかどうかを確認するための回避策を次に示します。

  1. ActivityManager.getRunningServices(max_count_of_services); を使用して、システムで実行中のサービスを確認します。
  2. 返された ActivityManager.RunningServiceInfo インスタンスから、ソフト キーボード サービスのclientCount値を確認します。
  3. 前述の clientCount は、ソフト キーボードが表示されるたびにインクリメントされます。たとえば、clientCount が最初は 1 だった場合、キーボードが表示されると 2 になります。
  4. キーボードを閉じると、clientCount が減少します。この場合、1 にリセットされます。

一部の一般的なキーボードには、classNames に特定のキーワードが含まれています。

  1. Google AOSP = IME
  2. スワイプ = IME
  3. Swiftkey = KeyboardService
  4. Fleksy = キーボード
  5. Adaptxt = IME (KPTAdaptxtIME)
  6. スマート = キーボード (SmartKeyboard)

ActivityManager.RunningServiceInfo から、ClassNames で上記のパターンを確認します。また、ActivityManager.RunningServiceInfo のclientPackage =android は、キーボードがシステムにバインドされていることを示します。

上記の情報を組み合わせて、ソフト キーボードが表示されているかどうかを厳密に確認できます。

于 2016-06-01T12:41:55.927 に答える
0

同様の問題がありました。画面上の Enter ボタンに反応する必要がありました (これにより、キーボードが非表示になりました)。この場合、キーボードを開いたときに使用したテキスト ビューの OnEditorAction をサブスクライブできます。編集可能なボックスが複数ある場合は、それらすべてをサブスクライブします。

アクティビティでは、キーボードを完全に制御できるため、すべての開始イベントと終了イベントをリッスンすれば、キーボードが開いているかどうかに関係なく問題に直面することはありません。

于 2011-01-25T16:39:23.027 に答える
0

答えをkotlinに変換しました。これがkotlinユーザーに役立つことを願っています。

private fun checkKeyboardVisibility() {
    var isKeyboardShowing = false

    binding.coordinator.viewTreeObserver.addOnGlobalLayoutListener {
        val r = Rect()
        binding.coordinator.getWindowVisibleDisplayFrame(r)
        val screenHeight = binding.coordinator.rootView.height

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        val keypadHeight = screenHeight - r.bottom


        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true

            }
        } else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false

            }
        }
    }
}
于 2019-06-16T06:56:03.363 に答える
0

アプリで AndroidR の API をサポートしている場合は、以下の方法を使用できます。

In kotlin :
    var imeInsets = view.rootWindowInsets.getInsets(Type.ime()) 
    if (imeInsets.isVisible) { 
        view.translationX = imeInsets.bottom 
    }

注:これはAndroidRでのみ利用可能で、Androidバージョン以下では他の回答に従う必要があります。そうしないと、そのために更新されます。

于 2020-02-25T06:01:02.307 に答える
-1

を使用している可能性があります:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    Log.d(
    getClass().getSimpleName(), 
    String.format("conf: %s", newConfig));

    if (newConfig.hardKeyboardHidden != hardKeyboardHidden) {
        onHardwareKeyboardChange(newConfig.hardKeyboardHidden);

        hardKeyboardHidden = newConfig.hardKeyboardHidden;
    }

    if (newConfig.keyboardHidden != keyboardHidden) {
        onKeyboardChange(newConfig.keyboardHidden);

        keyboardHidden = newConfig.hardKeyboardHidden;
    }

}

public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
public static final int KEYBOARDHIDDEN_NO = 1;
public static final int KEYBOARDHIDDEN_YES = 2;
public static final int KEYBOARDHIDDEN_SOFT = 3;

//todo
private void onKeyboardChange(int keyboardHidden) {

}

//todo
private void onHardwareKeyboardChange(int hardKeyboardHidden) {

}
于 2016-06-03T15:38:08.550 に答える
-1

私はこれを次のように行いましたが、あなたの目標がキーボードを閉じたり開いたりすることである場合にのみ関連します。

閉じる例: (キーボードが既に閉じているかどうかを確認し、そうでない場合は閉じる)

imm.showSoftInput(etSearch, InputMethodManager.HIDE_IMPLICIT_ONLY, new ResultReceiver(null) {
                    @Override
                    protected void onReceiveResult(int resultCode, Bundle resultData) {
                        super.onReceiveResult(resultCode, resultData);
                        if (resultCode != InputMethodManager.RESULT_UNCHANGED_HIDDEN)
                            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    }
                });
于 2015-06-26T11:45:44.707 に答える