Как определить, отображается ли программная клавиатура на устройстве Android?
есть ли способ В Android обнаружить, если программное обеспечение (a.к. a." мягкая") клавиатура видна на экране?
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. Поместите id в корневое представление
rootView
- это просто вид, указывающий на мой корневой вид в этом случае a 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) {
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, то эта функция возвращает true value....
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 будет инициализировано в false.
затем проверьте значение следующим образом и при необходимости выполните действие:
mSearchBox.requestFocus();
if(!isKeyboardActive()){
showKeyboard();
}else{
dismissKeyboard();
}
в моем случае у меня был только один EditText
для управления в моем макете, поэтому я придумал whit этой решение.
Он работает хорошо, в основном это custom 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 скрытый 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
У меня была похожая проблема. Мне нужно было реагировать на кнопку Enter на экране (которая скрывала клавиатуру). В этом случае вы можете подписаться на 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, когда клавиатура будет показана.
- при увольнении клавиатуры, clientCount уменьшается. В этом случае он сбрасывается на 1.
некоторые из популярных клавиатур имеют определенные ключевые слова в своих именах классов:
- Google AOSP = IME
- Swype = IME
- Swiftkey = KeyboardService
- Fleksy = клавиатура
- Adaptxt = IME (KPTAdaptxtIME)
- Smart = Клавиатура (SmartKeyboard)
Из ActivityManager.RunningServiceInfo, проверьте наличие вышеуказанных шаблонов в именах классов. Кроме Того, ActivityManager.RunningServiceInfo это clientPackage=android, что указывает на то, что клавиатура привязана к системе.
вышеупомянутая информация может быть объединена для строгого способа узнать, видна ли мягкая клавиатура.
Я сделал это следующим образом, но его relevet только если ваша цель-закрыть / открыть keyboad.
закрыть пример: (проверка, если клавиатура уже закрыта, если нет - закрытие)
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) {
}