Android: как я могу узнать, показывает ли программная клавиатура или нет?

Вот дилемма: я показываю экран с 3 полями ввода и 2 кнопками внутри вкладки (всего 3 вкладки, и они находятся в нижней части экрана). 2 кнопки расположены слева внизу и справа от экрана, прямо над вкладками. когда я нажимаю на поле ввода, все вкладки и кнопки нажимаются вверх на верхней части клавиатуры.

Я хочу только нажимать кнопки вверх и оставлять вкладки там, где они изначально находятся, внизу. я думаю о настройке видимости вкладок в состояние УДАЛЕНО, как только я определю, что экранная клавиатура отображается, и видимости ВИДИМОГО, когда экранная клавиатура исчезла.

есть ли какой-нибудь слушатель для софт-клавиатуры или, может быть, поле ввода? может быть, какое-то хитрое использование OnFocusChangeListener для редактирования текста? Как я могу определить, видна ли клавиатура или нет?

6 ответов

Решение

Определить, показывает ли клавиатура, по-видимому, невозможно.

Вы можете отключить все вместе с windowSoftInputMode тег xml в манифесте: http://developer.android.com/reference/android/R.attr.html. Или вы можете посмотреть, как снять фокусировку, чтобы скрыть клавиатуру: скрыть программную клавиатуру во время работы без каких-либо операций с клавиатурой.

Ни один из них точно не решит вашу проблему. Я помню, как читал пост в блоге, настоятельно советуя не использовать вкладки внизу, а не вверху экрана, для ясности пользовательского интерфейса. Я рекомендую вам следить за этим.

Насколько я знаю, ты не можешь.

Тем не менее, вы можете отслеживать изменения размера макета, и поскольку появление клавиатуры является основной причиной изменения размеров, вы можете предположить, что клавиатура отображается или нет.

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

public class LayoutSizeChangedSensorFrameLayout extends FrameLayout {
    public enum SizeChange {
        HEIGHT_INCREASED, HEIGHT_DECREASED, WIDTH_INCREASED, WIDTH_DECREASED
    }

    public interface OnLayoutSizeChangedListener {
        void onSizeChanged(EnumSet<SizeChange> direction);
    }

    private OnLayoutSizeChangedListener mLayoutSizeChangeListener;

    public LayoutSizeChangedSensorFrameLayout(final Context context) {
        super(context);
    }

    public LayoutSizeChangedSensorFrameLayout(final Context context, final AttributeSet attributeSet) {
        super(context, attributeSet);
    }

    public LayoutSizeChangedSensorFrameLayout(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
    }

  @Override
  protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
      super.onSizeChanged(w, h, oldw, oldh);
      if (mLayoutSizeChangeListener != null) {
          final EnumSet<SizeChange> result = EnumSet.noneOf(SizeChange.class);
          if (oldh > h)
              result.add(SizeChange.HEIGHT_DECREASED);
          else if (oldh < h)
              result.add(SizeChange.HEIGHT_INCREASED);
          if (oldw > w)
              result.add(SizeChange.WIDTH_DECREASED);
          else if (oldw < w)
              result.add(SizeChange.WIDTH_INCREASED);
          if (!result.isEmpty())
              mLayoutSizeChangeListener.onSizeChanged(result);
      }
  }

    public void setOnLayoutSizeChangedListener(final OnLayoutSizeChangedListener layoutSizeChangeListener) {
        this.mLayoutSizeChangeListener = layoutSizeChangeListener;
    }

    public OnLayoutSizeChangedListener getOnLayoutSizeChangeListener() {
        return mLayoutSizeChangeListener;
    }
}

Наконец-то я нашел решение после поиска нескольких классов. Я решил использовать WindowsInset, потому что он не вызывается каждую секунду, как использование глобального макета. Есть видео, рассказывающее о том, как использовать windowsInset. Связь

Это может помочь http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html

https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/latin

Код клавиатуры здесь, я немного обошел его, но сдался, я не вижу отправляемых трансляций, которые были бы полезны, по крайней мере, здесь. Может быть, вы можете найти код более низкого уровня в репозитории и найти полезную отправку намерений. Первый линк может сказать вам, когда он станет видимым, но я не уверен, как сказать, когда он станет невидимым.

Рабочее решение для меня -

ViewTreeObserver treeObserver = getViewTreeObserver();
        if (treeObserver != null)
            treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    int pHeight = getResources().getDisplayMetrics().heightPixels;

                Rect visRect = new Rect();
                viewGroup.getWindowVisibleDisplayFrame(visRect);

                boolean keyboardVisible;
                int keyboardHeight= pHeight-currentHeight;
                if (keyboardHeight > (MIN_KEYBOARD_HEIGHT*pHeight))
                {
                    TGVLog.d(debugTag, "keyboardVisible-- "+true);
                    keyboardVisible = true;
                }
                else
                {
                    TGVLog.d(debugTag, "keyboardVisible-- "+false);
                    keyboardVisible = false;
                }
                }
            });

В моем последнем приложении у меня были некоторые проблемы с отображением программной клавиатуры, затем я использовал следующий код в моем файле манифеста:

<activity android:screenOrientation="portrait" android:configChanges="keyboardHidden|orientation" android:name=".rate.Calculator"/>

Другие вопросы по тегам