Могу ли я одновременно иметь режим программной клавиатуры "AdjustResize" и панель инструментов за строкой состояния?

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

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

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

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

Я оставлю соответствующую цветную строку состояния ради 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 - Я прочитал десятки похожих вопросов о поведении программной клавиатуры, но не смог найти ничего полезного о непреднамеренных эффектах на Панели инструментов. Также, наоборот, много вопросов о стиле, касающихся поведения панели инструментов / строки состояния, но, на первый взгляд, они не актуальны. Тем не менее, извините, если я что-то пропустил!

Спасибо заранее!

редактировать

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

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

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

Так что я до сих пор именно там, где я начал:(

Добавление примера кода 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>

10 ответов

Решение

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

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

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

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

Решение:

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

  2. Цвет строки состояния. Это возможно только в 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's 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);
    }
    

Я нашел решение, которое, кажется, хорошо работает с ОС. Первый сет 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

Я думаю, что вы можете попробовать использовать "AdjustPan" вместо "AdjustResize", когда android:fitsSystemWindows="false". Меня устраивает.

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

Я столкнулся с подобной проблемой сcoordinatorLayout. Однако установкаfitsSystemWindowsкfalseрешил проблему. Похоже, что главный виновник — координаторLayout. Я решил эту проблему, инкапсулировав весь макет, включаяAppBarLayout, в течениеconstraintLayout.

      <androidx.coordinatorlayout.widget.CoordinatorLayout>
    <androidx.constraintlayout.widget.ConstraintLayout
          <com.google.android.material.appbar.AppBarLayout
           </com.google.android.material.appbar.AppBarLayout
         //content here
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

и конечноadjustResize

Я понимаю, что ответы на эту тему приходят довольно поздно, но, возможно, это может быть полезно другим. :)

Это работает для меня.

В файле manifest.xml поместите это в <activity> тег.

android:windowSoftInputMode="adjustResize"

Поместите это в родительский тег вашего макета.

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

Поместите это в styles.xml.

<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>

Я сделал это с minSdkVersion 16 и targetSdkVersion 26

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

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

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

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

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

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

Вот что сработало для меня, чтобы иметь как прозрачную строку состояния, так и рабочее поведение клавиатуры adjustResize.

Прежде всего, я предлагаю вам посмотреть 27-минутный доклад Криса Бэйнса о дроидконах, он может быть поучительным: https://www.youtube.com/watch?v=_mGDMVRO3iE

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

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

<!-- EditText etc here -->

В действии:

    makeStatusBarTransparent(this);
    setContentView(R.layout.activity_login);

Метод расширения:

fun Activity.makeStatusBarTransparent() {
window.apply {
    clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    decorView.systemUiVisibility += View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    // or:
    // decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
    statusBarColor = Color.TRANSPARENT
}
}

В теге активности в манифесте:

android:windowSoftInputMode="adjustResize|stateHidden"

Я решил сделать ".systemUiVisibility += ...", чтобы я мог установить некоторые вещи, такие как windowLightStatusBar в теме, через xml (я переопределяю его в разных вариантах). Но вы можете указать флаг LIGHT_STATUS_BAR напрямую (или нет, в зависимости от вашего фона).

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

Я исправил вашу проблему, а также проверил на моем конце. Пожалуйста, измените ваш относительный макет на 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>

Если вам все еще нужно какое-то решение - я нашел то, что работает для меня.

Посмотрите на мой XML, я объясню некоторые вещи ниже:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"                     //IMPORTANT
    android:background="@android:color/white">

    <RelativeLayout
        android:id="@+id/rl_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent">            //NO FITSYSTEMWINDOWS=TRUE

        <android.support.design.widget.CoordinatorLayout
            android:id="@+id/cl_root"
            android:layout_width="match_parent"
            android:layout_height="match_parent">            //NO FITSYSTEMWINDOWS=TRUE

            <android.support.design.widget.AppBarLayout
                android:id="@+id/ab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                android:fitsSystemWindows="true">                     //IMPORTANT

                <android.support.design.widget.CollapsingToolbarLayout
                    android:id="@+id/collapsing_toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="190dp"
                    android:fitsSystemWindows="true"                     //IMPORTANT
                    app:layout_scrollFlags="scroll|exitUntilCollapsed"
                    app:expandedTitleTextAppearance="@style/TransparentTextStyle"
                    app:collapsedTitleTextAppearance="@style/TransparentTextStyle"
                    app:contentScrim="@android:color/white"
                    app:expandedTitleMarginEnd="64dp"
                    app:expandedTitleMarginStart="48dp">

                    <FrameLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:fitsSystemWindows="true">                     //IMPORTANT

                        <ImageView
                            android:id="@+id/iv_pic"
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"/>

                        <ImageView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:background="@drawable/gradient_top_and_bottom_shadow"/>
                    </FrameLayout>

                    <android.support.v7.widget.Toolbar
                        android:id="@+id/toolbar"
                        android:layout_width="match_parent"
                        android:layout_height="?attr/actionBarSize"
                        android:elevation="7dp"
                        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                        app:layout_collapseMode="pin"
                        app:layout_scrollFlags="scroll|enterAlways">

                        <TextView
                            android:id="@+id/tv_title"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:fontFamily="@font/raleway_bold"
                            android:textSize="20sp"
                            android:lines="1"
                            android:ellipsize="end"
                            android:visibility="gone"
                            tools:text="Toolbar Text"/>

                    </android.support.v7.widget.Toolbar>
                </android.support.design.widget.CollapsingToolbarLayout>
            </android.support.design.widget.AppBarLayout>

            <android.support.v4.widget.SwipeRefreshLayout
                android:id="@+id/sr_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="-6dp"
                app:layout_behavior="@string/appbar_scrolling_view_behavior">

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/rv_event_details"
                    android:clipToPadding="false"
                    android:scrollbars="vertical"
                    android:scrollbarThumbVertical="@color/orange_juice_80"
                    android:scrollbarSize="2dp"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scrollbarStyle="outsideOverlay"
                    android:background="@drawable/shape_rounded_top_white" />
            </android.support.v4.widget.SwipeRefreshLayout>
        </android.support.design.widget.CoordinatorLayout>
    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

Я использую CL с CollapsingToolbarLayout, но это не имеет значения. Если вы хотите, чтобы это работало, выполните следующие шаги:

  1. Положил CoordinatorLayout в качестве коренного родителя в вашем XML и установить fitsSystemWindows="true" к этому;

  2. Положил RelativeLayout (или что вы хотите) в ваших родителей CoordinatorLayout, но НЕ УСТАНАВЛИВАЙТЕ fitsSystemWindows="true";

  3. Установите ОТРИЦАТЕЛЬНОЕ верхнее поле для вас RelativeLayout получая вашу высоту строки состояния программно и устанавливая цвет строки состояния как Color.TRANSPARENTвот мой код:

    public void AdjustActivityForTransparentStatusBar(логическая настройка) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (настройка) { if (findViewById(R.id.rl_root)!= null) { CoordinatorLayout.LaymsParams CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.MATCH_PARENT); params.setMargins(0, -Utils.getStatusBarHeight(), 0, 0); findViewById(R.id.rl_root).setLayoutParams(PARAMS); } getWindow().setStatusBarColor(Color.TRANSPARENT); } else { if (findViewById(R.id.rl_root)!= null) { CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.ENTCH__; params.setMargins(0, 0, 0, 0); findViewById(R.id.rl_root).setLayoutParams(PARAMS); } } } }

  4. Задавать fitsSystemWindows="true" некоторым дочерним представлениям, если они должны быть "ниже" вашей строки состояния. И теперь это должно работать.

PS: не знаю, почему я не могу сделать мой Java-код похожим на код здесь.

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