Могу ли я иметь "мягкую клавиатуру" "adjustResize" и панель инструментов за панель состояния одновременно?

В моем приложении Android для меня очень важно использовать поведение adjustResize для мягкой клавиатуры. Таким образом, пользователи могут прокручивать вниз до других элементов пользовательского интерфейса, например, кнопку "продолжить".

Я заметил, что adjustResize работает только тогда, когда у меня есть параметр Manifest и android:fitsSystemWindows="true" в корневом элементе макета. (Пожалуйста, поправьте меня, если я ошибаюсь!)

Но с android:fitsSystemWindows="true" панель инструментов больше не сидит за панель состояния. Что имеет смысл, но не то, что я хочу.

Когда панель инструментов находится за ней, строка состояния имеет соответствующий темный оттенок цвета панели инструментов. То, что у меня есть с android:fitsSystemWindows="true", - это бесцветная строка состояния и панель инструментов, которая находится на 24dp ниже, чем я хочу.

Я откажусь от соответствующей цветной строки состояния для поведения клавиатуры adjustResize. Но мой вопрос: возможно ли иметь и то и другое? Смею ли я мечтать о красоте и доступности?

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

FYI:

Это действия с корневыми элементами RelativeLayout, а в некоторых из них есть ListView и EditText.

Панель инструментов android.support.v7.widget.Toolbar

Потенциально соответствующие элементы стиля:

<style name="AppBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowContentOverlay">@null</item>

PS - Я читал десятки подобных вопросов о мягкой клавиатуре, но не смог найти ничего полезного в непреднамеренных эффектах на панели инструментов. Также наоборот, много вопросов о стиле панели инструментов/статусов, но ничего похожего на это. Тем не менее, извините, если я что-то пропустил!

Большое спасибо заранее!

Edit

Я играл с удалением android:fitsSystemWindows="true" и добавляю больше ScrollViews или пытаюсь получить все в одном ScrollView. Это ничего не делает.

Если я удалю android:fitsSystemWindows="true", тогда нижняя часть пользовательского интерфейса "склеивается" в нижней части экрана - он не "изменяет размер", а вместо этого приклеивается к верхней части мягкой клавиатуры, как я ожидал бы от нее с adjustResize, установленным в манифесте.

Настройка android:fitsSystemWindows="true" в корневом представлении делает изменение размера пользовательского интерфейса, как и следовало ожидать, но это также заставляет панель больше не заходить за статусBar.

Итак, я все еще точно начинаю: (

Добавление образца XML-кода макета:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 <!-- CoordinatorLayout because this view uses SnackBars -->

    <!-- Relative Layout to lock "continue" button bar to bottom -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Main content, that scrolls with or without keyboard -->
        <!-- Correctly sits behind transparent Status Bar -->
        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="@dimen/footer_persistent_height">
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">
                <!-- ACTUAL VIEWS DELETED FOR BREVITY / CLARITY -->
            </RelativeLayout>
        </android.support.v4.widget.NestedScrollView>


        <!-- Bottom nav bar -->
        <!-- Correctly sits at bottom of UI when keyboard is not visible -->
        <!-- PROBLEM: Not accessible when soft keyboard is visible -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            style="?android:attr/buttonBarStyle">

            <Button
                android:id="@+id/skip_button"
                android:theme="@style/ButtonContinueGrey"
                android:onClick="skipClickHandler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight=".5"
                style="?android:attr/buttonBarButtonStyle"/>

            <Button
                android:id="@+id/button_progress"
                android:theme="@style/ButtonContinueColored"
                android:onClick="continueClickHandler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight=".5"
                style="?android:attr/buttonBarButtonStyle"/>
        </LinearLayout>

    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

Ответ 1

(Отвечая на мой собственный вопрос)

Это похоже на ошибку в android: https://code.google.com/p/android/issues/detail?id=63777

Сообщения об этом сообщении об ошибке сообщают о нескольких предлагаемых работах, таких как создание настраиваемого класса Layout или специальной Soft Keyboard.

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

Решение:

  • Установите android:fitsSystemWindows="true" в корневом представлении макета или глобально в style.xml. Это (наряду с adjustResize в манифесте) заставляет пользовательский интерфейс сжиматься над Soft Keyboard, поэтому пользовательский интерфейс не блокируется - самое главное.

  • Цвет строки состояния. Это возможно только в Lollypop и новее. Во всяком случае, это то же самое, что и прозрачный StatusBar.

    private void updateStatusBarColor(){
        // Check Version
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // OPTIONAL: Calculate a darker version of the toolbar color
            int color = calculateDarkerColor(toolBarColor);
    
            // Get the statusBar
            Window window = getWindow();
            // You can't color a transparent statusbar
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            // Set the color
            window.setStatusBarColor(color);
        }
    }
    
    // Calculate a darker version of a given color
    // Note I do this because the color always changes, if it always the same I would save the darker version as a Resource in colors.xml
    private int calculateDarkerColor(int color){
        float[] hsv = new float[3];
        Color.colorToHSV(color, hsv);
        hsv[2] *= 0.8f; // smaller = darker
        return Color.HSVToColor(hsv);
    }
    

Ответ 2

Попробуйте сохранить макет в режиме прокрутки и удалить андроид: fitsSystemWindows = "true" и использовать только отрегулировать размер

Ответ 3

Я не получил ваш вопрос правильно, но насколько я могу понять, чтобы решить проблему -

Для проблемы с дополнением попробуйте добавить

android:fitsSystemWindows="true"
android:clipToPadding="false"

И для прозрачной строки состояния добавьте

<item name="android:statusBarColor">@android:color/transparent</item>

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

Ответ 4

Я исправляю вашу проблему, а также тестирую в конце. Пожалуйста, измените свой относительный макет на framelayout следующим образом:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- CoordinatorLayout because this view uses SnackBars -->

    <!-- Relative Layout to lock "continue" button bar to bottom -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

        <!-- Main content, that scrolls with or without keyboard -->
        <!-- Correctly sits behind transparent Status Bar -->
        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="24dp">
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">
                <!-- ACTUAL VIEWS DELETED FOR BREVITY / CLARITY -->
            </RelativeLayout>
        </android.support.v4.widget.NestedScrollView>


        <!-- Bottom nav bar -->
        <!-- Correctly sits at bottom of UI when keyboard is not visible -->
        <!-- PROBLEM: Not accessible when soft keyboard is visible -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            style="?android:attr/buttonBarStyle"
            android:layout_gravity="bottom">

            <Button
                android:id="@+id/skip_button"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight=".5"
                style="?android:attr/buttonBarButtonStyle"/>

            <Button
                android:id="@+id/button_progress"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight=".5"
                style="?android:attr/buttonBarButtonStyle"/>
        </LinearLayout>

    </FrameLayout>
</android.support.design.widget.CoordinatorLayout>

Ответ 5

Я нашел решение, которое, похоже, хорошо работает с ОС. Сначала установите fitSystemWindows = true на представление, которое вы хотите отреагировать на окно, а затем сообщите ему, чтобы игнорировать верхнее дополнение:

  ViewCompat.setOnApplyWindowInsetsListener(yourView, (view, insets) ->
      ViewCompat.onApplyWindowInsets(yourView,
          insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0,
              insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()))
  );

Подробнее здесь: https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec