ソフトウェアキーボードがAndroidデバイスで表示されているかどうかを検出するにはどうすればよいですか?


Answers

これは私のために働く。 たぶん、これは常にすべてのバージョンにとって最良の方法です

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
    }
    else {
        // keyboard is closed
    }
}
});
Question

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




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

それは毎回私のために働いた。

adb shell dumpsys window InputMethod | grep "mHasSurface"

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




@iWantScalaの回答は素晴らしいですが、私には役に立たない
rootView.getRootView().getHeight()常に同じ値を持ちます

1つの方法は、2つの変数を定義することです

private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;

グローバルリスナーを追加

rootView.getViewTreeObserver()
    .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            currentRootViewHeight = rootView.getHeight();
            if (currentRootViewHeight > maxRootViewHeight) {
                maxRootViewHeight = currentRootViewHeight;
            }
        }
    });

次にチェックする

if (currentRootViewHeight >= maxRootViewHeight) {
    // Keyboard is hidden
} else {
    // Keyboard is shown
}

正常に動作します




final View activityRootView = findViewById(R.id.rootlayout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            Rect r = new Rect();
            activityRootView.getWindowVisibleDisplayFrame(r);

            int screenHeight = activityRootView.getRootView().getHeight();
            Log.e("screenHeight", String.valueOf(screenHeight));
            int heightDiff = screenHeight - (r.bottom - r.top);
            Log.e("heightDiff", String.valueOf(heightDiff));
            boolean visible = heightDiff > screenHeight / 3;
            Log.e("visible", String.valueOf(visible));
            if (visible) {
                Toast.makeText(LabRegister.this, "I am here 1", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(LabRegister.this, "I am here 2", Toast.LENGTH_SHORT).show();
            }
        }
});



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

  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. Swype = IME
  3. Swiftkey = KeyboardService
  4. フレッシ=キーボード
  5. Adaptxt = IME(KPTAdaptxtIME)
  6. スマート=キーボード(SmartKeyboard)

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

上記の情報を組み合わせて、ソフトキーボードが見えるかどうかを厳密に判断することができます。




私の場合、私は私のレイアウトで管理するEditTextが1つしかなかったので、私はthis解決策を思いついた。 それはうまくいきます、基本的には、フォーカスを聞いてフォーカスが変わった場合、または戻る/完了ボタンが押された場合にローカルブロードキャストを送信するカスタムEditTextです。 作業するには、 android:focusable="true"およびandroid:focusableInTouchMode="true"してレイアウトにダミーViewを配置する必要がありandroid:focusableInTouchMode="true"なぜなら、 clearFocus()を呼び出すと、フォーカスは最初のフォーカス可能なビューに再割り当てされるからです。 ダミービューの例:

<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>

その他の情報

レイアウトの変更の違いを検出するソリューションは、画面の密度に強く依存するため、うまく機能しません。特定のデバイスでは100pxが多く、誤検出を起こす可能性があるためです。 また、ベンダーによって異なるキーボードがあります。




私はこれを基礎として使った: http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android : http://www.ninthavenue.com.au/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);

間違いなく理想的な解決策ですが、それは仕事を完了します。




私の最高の経験は自分のキーボードを作ったことでした




これを見つけるための直接的な方法があります。 そして、それはレイアウトの変更を必要としません。
したがって、没入型フルスクリーンモードでも動作します。
しかし、残念ながら、すべてのデバイスで動作するわけではありません。 だからあなたのデバイスでそれをテストする必要があります。

そのトリックは、ソフトキーボードを隠したり表示したり、その試行の結果をキャプチャしようとすることです。
正しく動作する場合、キーボードは実際には表示されず、隠されません。 私たちはただの状態を求めます。

最新の状態に保つためには、ハンドラを使用してこの操作を繰り返します(200ミリ秒ごとなど)。

以下の実装では、単一のチェックしか行いません。
複数のチェックを行う場合は、すべての(_keyboardVisible)テストを有効にする必要があります。

public interface OnKeyboardShowHide
{
    void    onShowKeyboard( Object param );
    void    onHideKeyboard( Object param );
}

private static Handler      _keyboardHandler    = new Handler();
private boolean             _keyboardVisible    = false;
private OnKeyboardShowHide  _keyboardCallback;
private Object              _keyboardCallbackParam;

public void start( OnKeyboardShowHide callback, Object callbackParam )
{
    _keyboardCallback      = callback;
    _keyboardCallbackParam = callbackParam;
    //
    View view = getCurrentFocus();
    if (view != null)
    {
        InputMethodManager imm = (InputMethodManager) getSystemService( Activity.INPUT_METHOD_SERVICE );
        imm.hideSoftInputFromWindow( view.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY, _keyboardResultReceiver );
        imm.showSoftInput( view, InputMethodManager.SHOW_IMPLICIT, _keyboardResultReceiver );
    }
    else // if (_keyboardVisible)
    {
        _keyboardVisible = false;
        _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
    }
}

private ResultReceiver      _keyboardResultReceiver = new ResultReceiver( _keyboardHandler )
{
    @Override
    protected void onReceiveResult( int resultCode, Bundle resultData )
    {
        switch (resultCode)
        {
            case InputMethodManager.RESULT_SHOWN :
            case InputMethodManager.RESULT_UNCHANGED_SHOWN :
                // if (!_keyboardVisible)
                {
                    _keyboardVisible = true;
                    _keyboardCallback.onShowKeyboard( _keyboardCallbackParam );
                }
                break;
            case InputMethodManager.RESULT_HIDDEN :
            case InputMethodManager.RESULT_UNCHANGED_HIDDEN :
                // if (_keyboardVisible)
                {
                    _keyboardVisible = false;
                    _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
                }
                break;
        }
    }
};



私はこのために使用できるシンプルなクラスを作成しました: https://github.com/ravindu1024/android-keyboardlistener : https://github.com/ravindu1024/android-keyboardlistener 。 プロジェクトにコピーして、次のように使用してください:

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});



私も同様の問題がありました。 私は画面上のEnterボタン(キーボードを隠していた)に反応する必要がありました。 この場合、キーボードが持つテキストビューのOnEditorActionを購読することができます。複数の編集可能なボックスがある場合は、そのすべてをサブスクライブします。

あなたのアクティビティではキーボードを完全にコントロールしていますので、開いているかどうかに関わらず、すべての開始イベントと終了イベントを聴くと、問題に直面しません。