Android appcompat toolbar stretches when searchview gets focus
Asked Answered
G

10

22

I'm updating an app to use the new Toolbar instead of the regular ActionBar. In my app the user must be able to select a contact from their contact list. To do so, I've added a SearchView to the menu. The contacts are already in the list; the SearchView is used to filter the list using the ArrayAdapter.getFilter() method.

It all worked fine using the ActionBar, but the Toolbar's height gets stretched to just behind the keyboard. Using the XML inspection from Android Device Monitor I can see the ListView exists behind my keyboard.

It almost seems as if the SearchView wants to display suggestions, but I have no such thing configured. Any idea what's going wrong?

The images illustrate the problem. They show the normal, expanded and focused state of the SearchView.

This is my XML menu:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/action_forwarding_contact_search"
        app:showAsAction="always"
        android:title="@string/forwarding_contact_search"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:icon="@drawable/abc_ic_search_api_mtrl_alpha"/>
</menu>

Edit Giving the Toolbar a fixed height doesn't solve the problem, because it will make SearchView disappear when it has focus. Changing the gravity of either item seems to have no effect on the SearchView.

Normal state Expanded state Focused state

Guddle answered 20/1, 2015 at 10:38 Comment(2)
It's really strange and annoying. Even when I start ActionMode with a SearchView, the issue occurs for the Toolbar. The ActionMode bar stays intact, but the rest of the screen is filled with the ToolBar's color.Guddle
I just remove fitsSystemWindows=true from theme and set to root view in xml. It helps.Amoroso
G
19

Ok, I figured it out. There was no problem with the SearchView, because the same happened with ordinary EditTexts which were placed normally inside a layout xml. The Toolbar wasn't the problem either.

I created an empty activity and played around with anything I changed in my app and finally came to my theme. On KitKat and later I had <item name="android:windowTranslucentStatus">true</item> set on the theme, so the navigation drawer would appear behind the status bar.

Disabling/removing this would resolve the issue. This reminded me of the android:fitsSystemWindows="true" property. It is set on the Toolbar, but not in the layout xml of the main activity that contains the DrawerLayout. I guess the DrawerLayout sets itself to fit the system windows. E.g. there's no fitSystemWindows property here:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DashboardActivity">

The activity where the problem occurred did not have a NavigationDrawer, it was a new activity. Setting android:fitsSystemWindows="true" on the root node of the layout of the activity made things work fine.

So, for anyone to read this: if you have <item name="android:windowTranslucentStatus">true</item> in your theme, make sure any root node containing a toolbar contains a android:fitsSystemWindows="true".

Working sample:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <include layout="@layout/toolbar" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <EditText
                android:id="@+id/editText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true" />

            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="New Button" />
        </LinearLayout>
</LinearLayout>
Guddle answered 22/1, 2015 at 13:7 Comment(5)
I had this problem too - but I have to ask, what's the purpose of having a translucent status bar if we can't have anything behind it when a toolbar is being used?Gimlet
I was able to both solve the problem and show stuff behind the status bar by wrapping the Toolbar's container in another layout that doesn't fitSystemWindows.Gimlet
I was going to say that it's not possible, but it's cool you got it to work. The Play Store app doesn't show anything behind the status bar either. I think the purpose of a 'translucent' status bar is that you can draw your layout behind it when going full screen, without an actionbar/toolbar.Guddle
Great analysis. But another problem happen. When I add android:fitsSystemWindows="true" on the root node, the immersing effect of status bar disappear. How do you sovle it?Copalm
@VictorChoy same happened in my case; I found Rob's answer based on adding android:windowSoftInputMode="adjustPan" in the manifest the preferable solution.Comprador
G
26

I had the same problem than OP, I tried the android:fitsSystemWindows="true" solution, but it was half resolved: the searchview didn't expand anymore but the notification bar (top of screen) became totally white (like the layout background) instead of red (my app theme).

I found an alternative way and it's working like a charm, so for those who are stuck, try this:

In your manifest, just add this line in your activity section:

android:windowSoftInputMode="adjustPan"

Example:

<activity
    android:name=".MainActivity"
    android:windowSoftInputMode="adjustPan"
    android:label="My main activity" >
</activity>
Gib answered 10/6, 2015 at 21:20 Comment(0)
G
19

Ok, I figured it out. There was no problem with the SearchView, because the same happened with ordinary EditTexts which were placed normally inside a layout xml. The Toolbar wasn't the problem either.

I created an empty activity and played around with anything I changed in my app and finally came to my theme. On KitKat and later I had <item name="android:windowTranslucentStatus">true</item> set on the theme, so the navigation drawer would appear behind the status bar.

Disabling/removing this would resolve the issue. This reminded me of the android:fitsSystemWindows="true" property. It is set on the Toolbar, but not in the layout xml of the main activity that contains the DrawerLayout. I guess the DrawerLayout sets itself to fit the system windows. E.g. there's no fitSystemWindows property here:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DashboardActivity">

The activity where the problem occurred did not have a NavigationDrawer, it was a new activity. Setting android:fitsSystemWindows="true" on the root node of the layout of the activity made things work fine.

So, for anyone to read this: if you have <item name="android:windowTranslucentStatus">true</item> in your theme, make sure any root node containing a toolbar contains a android:fitsSystemWindows="true".

Working sample:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <include layout="@layout/toolbar" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <EditText
                android:id="@+id/editText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true" />

            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="New Button" />
        </LinearLayout>
</LinearLayout>
Guddle answered 22/1, 2015 at 13:7 Comment(5)
I had this problem too - but I have to ask, what's the purpose of having a translucent status bar if we can't have anything behind it when a toolbar is being used?Gimlet
I was able to both solve the problem and show stuff behind the status bar by wrapping the Toolbar's container in another layout that doesn't fitSystemWindows.Gimlet
I was going to say that it's not possible, but it's cool you got it to work. The Play Store app doesn't show anything behind the status bar either. I think the purpose of a 'translucent' status bar is that you can draw your layout behind it when going full screen, without an actionbar/toolbar.Guddle
Great analysis. But another problem happen. When I add android:fitsSystemWindows="true" on the root node, the immersing effect of status bar disappear. How do you sovle it?Copalm
@VictorChoy same happened in my case; I found Rob's answer based on adding android:windowSoftInputMode="adjustPan" in the manifest the preferable solution.Comprador
S
17

I had same issue like this but did't help above answers but after lots of search found something.

may help you too.!!

after add this attribute in toolbar

android:layout_height="?attr/actionBarSize"

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/ToolBarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/myPrimaryColor"
android:minHeight="@dimen/abc_action_bar_default_height_material" >

<TextView
    android:id="@+id/toolbar_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="18sp"
    android:textColor="@color/myTextPrimaryColor"
    android:layout_gravity="center" />

</android.support.v7.widget.Toolbar>
Scan answered 27/6, 2015 at 15:18 Comment(3)
this indeed prevents the toolbar from expanding, but the toolbar title disappears and the size of the toolbar is too small - i.e. it chops the text.Zinc
its happening in all device or some specific device. and you can also use material design android:minHeight="@dimen/abc_action_bar_default_height_material" if you have appcompatScan
greatest solution i ever seen...+1 vote up for me Thanks.Booklover
R
3

The accepted answer works fine, however I needed an alternative that would allow to view the Toolbar under translucent status bar.

The problem is that Toolbar uses paddings to cover for system components. As a result, the paddingBottom of the Toolbar is being set to soft keyboard's height whenever the keyboard appears. Solution was to reset the padding before calling super.onMeasure in my custom Toolbar class:

public class MyToolbar extends Toolbar {

   (...)

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
       setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), 0);
       super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
Roughdry answered 10/6, 2015 at 13:21 Comment(0)
G
2

It seems like a old question but I want to address the real cause about this issue.

In fact, the fitsSystemWindows does not only add statusBar insets into your views padding, but also keyboard's height. So, when keyboard showed, your toolbar(which is the view who consumes window insets) will gain a bottom padding equals to your keyboard's height.

Move fitSystemWindows to root node do solve this problem, but sometimes we can't do that, for example we need toolbar's background to fill the statusbar.

So, the real solution for this issue, I think, is to tell view only consume top insets. Luckily, Android do offer a method for us to do that.

private static final View.OnApplyWindowInsetsListener CONSUME_TOP_INSET_LISTENER = new View.OnApplyWindowInsetsListener() {
    @RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
    @Override
    public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
        int b = v.getPaddingBottom();
        int l = v.getPaddingLeft();
        int r = v.getPaddingRight();

        v.setPadding(l, insets.getSystemWindowInsetTop(), r, b);
        int il = insets.getSystemWindowInsetLeft();
        int ir = insets.getSystemWindowInsetRight();
        int ib = insets.getSystemWindowInsetBottom();
        return insets.replaceSystemWindowInsets(il, 0, ir, ib);
    }
};
public static void makeViewConsumeTopWindowInsetsOnly(@NonNull View view) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
        view.setOnApplyWindowInsetsListener(CONSUME_TOP_INSET_LISTENER);
    }
}

Add above code to some place, and call this method with the view you want to consumes top insets.

Gamali answered 15/8, 2018 at 8:29 Comment(0)
B
1

I had the same issue with a SearchView on a Toolbar with a TextView and Spinner in it. Closing the SearchView (either by pressing the Toolbar back button or by switching to a different tab in the ViewPager) caused the Toolbar to stretch out to just below the top of the keyboard.

I solved it by placing an extra layout around the views in my Toolbar.

Before:

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

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

        <Spinner
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

</android.support.v7.widget.Toolbar>

After

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

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

        <Spinner             
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>

</android.support.v7.widget.Toolbar>
Bent answered 21/6, 2015 at 14:33 Comment(0)
S
1

I ran into a similar issue and setting showAsAction="always|collapseActionView" inside the Search Menu Item (menu.xml) solved the stretching of the toolbar for me.

Shakhty answered 15/9, 2015 at 10:21 Comment(0)
D
1

simplest solution without changing xml and keeping translucent system bar is to add: kotlin:

toolbar.setOnApplyWindowInsetsListener { toolbar, windowInsets ->
    toolbar.updatePadding(
        windowInsets.systemWindowInsetLeft, 
        windowInsets.systemWindowInsetTop,
        windowInsets.systemWindowInsetRight,
        0
    )
    windowInsets.consumeSystemWindowInsets()
}

please check if your fitsSystemWindows=true are placed correctly.

Descriptive answered 26/11, 2018 at 13:50 Comment(1)
This is the correct solution nowadays due to the support to display cutout. When keyboard is open, systemWindowInsetBottom is greather than 0 leading to behavior mentioned by OP. With this solution, you fixes bottom padding to 0 (and no longer attached to systemWindowInsetBottom).Guildsman
G
0

I would like to share my experience but before that I want to dropped this comment. So far, I really find this CoordinatorLayout shenanigans buggy and not worthy of being dropped in the SDK. Its just buggy. When it behaves like this erratically, the architecture on the xml layout is not much of a help to figure out whats going on. I followed the examples religiously and none of them worked.

Having said that, I am using the build tools version v24.0.2 (The latest as of this writing) and my situation may be of different than the rest. So I am putting this answer along with other answers here.

In my case, I am using this library for NavigationDrawer

As some answers here pointed out, its the navigation drawer. I tried not using that library and still having the problem. I have CoordinatorLayout as the parent layout of my two activities and programatically inserts the NavigationDrawer as instructed by the library author. The expanding Toolbar the size of the screen when focusing on an EditText is still there. Therefore, in my case, the problem is not coming from there.

Here's what I did in my case:

I removedfitsSystemWindows from the CoordinatorLayout layout of the activity. Contrary to what other people suggested here.

I am pasting my entire activity layout here:

<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/coordinatorlayout_homescreen"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.HomeScreenActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingtoolbarlayout_homescreen"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="64dp"
            app:expandedTitleMarginEnd="48dp"
            app:layout_scrollFlags="scroll|enterAlwaysCollapsed">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar_homescreen"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="pin"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <FrameLayout
            android:id="@+id/framelayout_homescreen"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v4.widget.NestedScrollView>

    <!--
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_homescreen"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />
    -->

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

I did this on another activity and it works as expected. I don't have the expanding Toolbar anymore. But this problem occurred. I am about to pull my hair out. The status bar became white. Phoenix Wang solution on that post fix it for me and I quote his answer:

I found the answer in this link:Status Bar Color not changing with Relative Layout as root element

So it turns out we need remove the

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

styles.xml(v21). And it works just fine for me.

My only concern is how will this solution holds in the upcoming updates. CoordinatorLayout should not be behaving like that.

Gingras answered 24/9, 2016 at 9:22 Comment(0)
S
0

In case you are using an EditText inside Toolbar, adding "flagNoExtractUi" in imeOptions , will solve the stretching edit area.

EditText for Search Action without stretching:

android:id="@+id/toolbar_editText"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:inputType="text"
android:imeOptions="actionSearch|flagNoExtractUi"
android:singleLine="true" />
Scouting answered 13/6, 2017 at 9:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.