Как определить, отображается ли программная клавиатура на устройстве 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

Есть ли способ в Android определить, отображается ли на экране программное обеспечение (ака «мягкая») клавиатура?




Вы можете обратиться к этому ответу - https://.com/a/24105062/3629912

Он работал для меня каждый раз.

adb shell dumpsys window InputMethod | grep "mHasSurface"

Он вернет true, если будет видна программная клавиатура.




Ответ @iWantScala велик, но не работает для меня
rootView.getRootView().getHeight() всегда имеет такое же значение

одним из способов является определение двух варов

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
}

работает отлично




В моем случае у меня был только один EditText для управления в моем макете, поэтому я подошел к this решению. Он хорошо работает, в основном это настраиваемый EditText который прослушивает фокус и отправляет локальную широковещательную рассылку, если фокус меняется или нажата кнопка «Назад / Готово». Для работы вам нужно поместить манекен View в ваш макет с помощью android:focusable="true" и android:focusableInTouchMode="true" потому что, когда вы вызываете clearFocus() фокус будет переназначен в первый настраиваемый вид. Пример фиктивного представления:

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

Дополнительная информация

Решение, которое обнаруживает разницу в изменениях компоновки, не очень хорошо работает, поскольку оно сильно зависит от плотности экрана, так как 100px может быть много в определенном устройстве, и ничто в некоторых других случаях вы не можете получить ложные срабатывания. У разных производителей разные клавиатуры.




Существует прямой способ найти это. И это не требует изменений макета.
Таким образом, он работает и в полноэкранном режиме.
Но, к сожалению, он не работает на всех устройствах. Поэтому вы должны протестировать его с помощью вашего устройства (ов).

Фокус в том, что вы пытаетесь скрыть или показать мягкую клавиатуру и зафиксировать результат этой попытки.
Если он работает правильно, клавиатура на самом деле не отображается или скрыта. Мы просто просим государство.

Чтобы оставаться в курсе последних событий, вы просто повторяете эту операцию, например каждые 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;
        }
    }
};



У меня была аналогичная проблема. Мне нужно было реагировать на кнопку Enter на экране (которая скрывала клавиатуру). В этом случае вы можете подписаться на OnEditorAction текстового представления, с которым была открыта клавиатура, - если у вас есть несколько редактируемых блоков, а затем подписаться на все из них.

В вашей деятельности у вас есть полный контроль над клавиатурой, поэтому ни при каких обстоятельствах вы не столкнетесь с проблемой, открыта ли клавиатура или нет, если вы слушаете все события открытия и закрытия.




Я использовал это в качестве основы: 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);

Довольно не идеальное решение, но оно выполняет свою работу.




Мой лучший опыт заключался в том, чтобы сделать свою собственную клавиатуру




Я создал простой класс, который можно использовать для этого: https://github.com/ravindu1024/android-keyboardlistener . Просто скопируйте его в свой проект и используйте следующее:

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



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.

Некоторые из популярных клавиатур имеют определенные ключевые слова в своих именах классов:

  1. Google AOSP = IME
  2. Swype = IME
  3. Swiftkey = KeyboardService
  4. Fleksy = клавиатура
  5. Adaptxt = IME (KPTAdaptxtIME)
  6. Smart = клавиатура (SmartKeyboard)

Из ActivityManager.RunningServiceInfo проверьте указанные шаблоны в ClassNames. Кроме того, clientManager.RunningServiceInfo clientPackage = android указывает, что клавиатура привязана к системе.

Вышеупомянутая информация может быть объединена для строгой проверки того, видна ли мягкая клавиатура.




Related