Могу ли я одновременно иметь режим программной клавиатуры "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.
Я чувствую, что уже потратил достаточно времени на это. Поэтому мое решение - просто раскрасить строку состояния вручную.
Решение:
Задавать
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'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, но это не имеет значения. Если вы хотите, чтобы это работало, выполните следующие шаги:
Положил
CoordinatorLayout
в качестве коренного родителя в вашем XML и установитьfitsSystemWindows="true"
к этому;Положил
RelativeLayout
(или что вы хотите) в ваших родителейCoordinatorLayout
, но НЕ УСТАНАВЛИВАЙТЕfitsSystemWindows="true"
;Установите ОТРИЦАТЕЛЬНОЕ верхнее поле для вас
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); } } } }
Задавать
fitsSystemWindows="true"
некоторым дочерним представлениям, если они должны быть "ниже" вашей строки состояния. И теперь это должно работать.
PS: не знаю, почему я не могу сделать мой Java-код похожим на код здесь.