22 ответов:
нет прямого пути-см. http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a где Диана Хакборн из команды Android ответила. Однако вы можете обнаружить его косвенно, проверив, изменился ли размер окна в #onMeasure. Смотрите Как проверить видимость программной клавиатуры в Android?.
это работает для меня. Может быть, это всегда лучший способ для всех версий.
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 } } });
попробуйте это:
InputMethodManager imm = (InputMethodManager) getActivity() .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.isAcceptingText()) { writeToLog("Software Keyboard was shown"); } else { writeToLog("Software Keyboard was not shown"); }
Я создал простой класс, который можно использовать для этого:https://github.com/ravindu1024/android-keyboardlistener. Просто скопируйте его в свой проект и используйте следующим образом:
KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener() { @Override public void onToggleSoftKeyboard(boolean isVisible) { Log.d("keyboard", "keyboard visible: "+isVisible); } });
Очень Просто
1. Поместите идентификатор в корневой вид
rootViewэто просто вид, указывающий на мой корневой вид в этом случае arelative 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) { Log.e("MyActivity", "keyboard opened"); } else { Log.e("MyActivity", "keyboard closed"); } } });
вы можете использовать результат обратного вызова showSoftInput() и hideSoftInput() для проверки состояния клавиатуры. Полная информация и пример кода на
http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android
вы можете обратиться к этому ответу -https://stackoverflow.com/a/24105062/3629912
Он работал для меня каждый раз.
adb shell dumpsys window InputMethod | grep "mHasSurface"он вернет true, если видна программная клавиатура.
я использовал это в качестве основы: 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 и т. д.), которые могли открыть softkeyboard:
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);Addmittely не идеальное решение, но он получает работу.
Я сделал это, установив 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 } } });
попробуйте этот код он действительно работает, если KeyboardShown отображается, то эта функция возвращает истинное значение....
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; }
Это было гораздо проще для требований, которые мне нужны. Надеюсь, что это может помочь:
на в 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 будет инициализировано в ложные.
затем проверьте значение следующим образом и при необходимости выполните следующее действие:
mSearchBox.requestFocus(); if(!isKeyboardActive()){ showKeyboard(); }else{ dismissKeyboard(); }
в моем случае у меня был только один
EditTextчтобы управлять в моем макете, поэтому я придумал whit этой решение. Он работает хорошо, в основном это обычай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 может быть много в определенном устройстве и ничего в некоторых других вы можете получить ложные срабатывания. Также разные производители имеют разные клавиатуры.
ответ @iWantScala велик, но не работает для меня
rootView.getRootView().getHeight()всегда имеет одно и то же значениеодин из способов-определить два vars
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 }работает отлично
Я думаю, что это старый вопрос, но сегодня я сталкиваюсь с хорошей библиотекой, чтобы определить, открыта клавиатура или нет. Так что я делюсь здесь.
У меня была похожая проблема и я нашел одну библиотеку для этого, и я играл с ним. Это работает, как очищаться. Вот он Библиотека Клавиатура.
Итак, после долгого времени игры с AccessibilityServices, оконными вставками, обнаружением высоты экрана и т. д., Я думаю, что нашел способ сделать это.
отказ от ответственности: он использует скрытый метод в Android, что означает, что он может быть не последовательным. Однако, в моем тестировании, это, кажется, работает.
метод InputMethodManager#getInputMethodWindowVisibleHeight (), и он существовал с Lollipop (5.0).
вызов, который возвращает высоту, в пикселы, текущей клавиатуры. Теоретически клавиатура не должна быть высотой 0 пикселей, поэтому я сделал простую проверку высоты (в Котлине):
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
У меня была похожая проблема. Мне нужно было реагировать на кнопку ввода на экране (которая скрывала клавиатуру). В этом случае вы можете подписаться на OnEditorAction текстового представления клавиатура была открыта с - если у вас есть несколько редактируемых полей, а затем Подписаться на все из них.
в вашей деятельности у вас есть полный контроль над клавиатурой, поэтому ни в коем случае вы не столкнетесь с проблемой, открыта ли клавиатура или нет, если вы слушаете все события открытия и закрытия.
существует прямой метод, чтобы узнать это. И, это не требует изменения макета.
Так что он работает и в иммерсивном полноэкранном режиме.
Но, к сожалению, он работает не на всех устройствах. Таким образом, вы должны проверить его с помощью устройства(ов).
Хитрость заключается в том, что вы пытаетесь скрыть или показать мягкую клавиатуру и захватить результат этой попытки.
Если он работает правильно, то клавиатура на самом деле не отображается или скрыта. Мы просто просим государство.
Остаться до настоящего времени вы просто повторяете эту операцию, например, каждые 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; } } };
в 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(); } } }
вот обходной путь, чтобы узнать, видна ли softkeyboard.
- проверьте наличие запущенных служб в системе с помощью ActivityManager.getRunningServices (max_count_of_services);
- из возвращенного ActivityManager.Экземпляры RunningServiceInfo, проверить clientCount значение для обслуживания мягкой клавиатуры.
- вышеупомянутый clientCount будет увеличиваться каждый раз, когда отображается мягкая клавиатура. Например, если clientCount изначально был 1, это будет 2, когда клавиатура отображается.
- при увольнении с клавиатуры количество клиентов уменьшается. В этом случае он сбрасывается на 1.
некоторые из популярных клавиатур имеют определенные ключевые слова в их именах классов:
- Google AOSP = IME
- Swype = IME
- Swiftkey = KeyboardService
- Fleksy = клавиатура
- Adaptxt = IME (KPTAdaptxtIME)
- Smart = Клавиатура (SmartKeyboard)
Из ActivityManager.RunningServiceInfo, проверьте наличие вышеуказанных шаблонов в именах классов. Кроме Того, ActivityManager.RunningServiceInfo это clientPackage=android, что указывает на то, что клавиатура привязана к системе.
вышеупомянутая информация может быть объединена для строгого способа узнать, видна ли мягкая клавиатура.
Я сделал это следующим образом, но его релевантность только в том случае, если ваша цель-закрыть / открыть клавиатуру.
закрыть пример: (проверка, если клавиатура уже закрыта, если нет - закрытие)
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); } });
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(); } } });
a может использовать :
@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) { }
Comments