In my Android app, it is vital for me to use the adjustResize
behavior for the soft keyboard. So users can scroll down to other UI elements, such as a "continue" button.
I've noticed that that adjustResize
only works when I have both the Manifest setting and android:fitsSystemWindows="true"
in the layout root element. (Please correct me if I'm wrong!)
But with android:fitsSystemWindows="true"
the Toolbar no longer sits behind the Status Bar. Which makes perfect sense, but isn't what I want.
When the Toolbar sits behind it, the status bar has a matching darker shade of my Toolbar's color. What I have with android:fitsSystemWindows="true"
is a colorless status bar and a toolbar that sits 24dp lower than I want it.
I will give up the matching colored Status Bar for the sake of the adjustResize
keyboard behavior. But my question is, is it possible to have both? Dare I dream for both Beauty and Accessibility?
Anyone more experienced know the magical combination of settings? Or perhaps, as a work around, a way to explicitly color the status bar?
fyi:
These are Activities with RelativeLayout root elements, and there are ListView
s and EditText
s in some of them.
Toolbar is android.support.v7.widget.Toolbar
Potentially relevant Style items:
<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 - I've read dozens of similar-ish questions on soft keyboard behavior, but was unable to find anything helpful on unintended effects to the Toolbar. Also vice versa, lots of Style questions about toolbar/statusbar behavior, but nothing seemingly relevant. Never the less, sorry if I missed something!
Many thanks in advance!
Edit
I've been playing with removing android:fitsSystemWindows="true"
and adding more ScrollViews or trying to get everything into the same ScrollView. This does nothing.
If I remove android:fitsSystemWindows="true"
then the bottom of the UI is "glued" to the bottom of the screen -- it does not "resize" to instead glue to the top of the soft keyboard like I would expect it to do with adjustResize
set in the Manifest.
Setting android:fitsSystemWindows="true"
in the root view makes the UI resize like I would expect -- but it also makes the toolbar no longer draw behind the statusBar.
So I am still exactly where I started :(
Adding a layout XML code sample:
<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>
(Answering my own question)
This does seem to be a bug in android: https://code.google.com/p/android/issues/detail?id=63777
Posts on the above bug report link to a few suggested work arounds, like creating a custom Layout class or custom Soft Keyboard.
I feel like I've already wasted enough time with this. So my solution is to just manually color the Status Bar.
Solution:
Set android:fitsSystemWindows="true"
in either the Layout's root view or globally in style.xml. This (along with adjustResize in the manifest) makes the UI shrink above the Soft Keyboard so no UI is blocked -- the most important thing.
Color the Status Bar. This is only possible in Lollypop and newer. Which is the same as the transparent StatusBar, anyway.
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);
}