Search code examples
androidandroid-actionbarsearchview

Android ActionBar: collapsible SearchView with action button


How to build ActionBar with collapsible search view with single action item visible, when search view is expanded? To be more descriptive, this is what I need:

enter image description here Note that there are other menu items and android:uiOptions="splitActionBarWhenNarrow" is defined in AndroidManifest.xml.

I tried to set up custom search item layout:

menu.xml

<item
    android:id="@+id/menu_search"
    android:actionLayout="@layout/actionbar_search"
    android:icon="@drawable/action_search"
    android:showAsAction="always|collapseActionView"
    android:title="@string/search" />

actionbar_search.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="right"
    android:orientation="horizontal" >

    <com.actionbarsherlock.widget.SearchView
        android:id="@+id/search_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:iconifiedByDefault="false"
        android:queryHint="@string/search_hint" />

    <ImageButton
        android:id="@+id/add_item"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        style="@style/Widget.Sherlock.ActionButton"
        android:src="@drawable/content_new"/>

</LinearLayout>

But by default search view takes all available width and button is not visible. I don't know how to force SearchView to fill all available space between app icon and menu item. All I found is android:maxWidth property, but this only allows to hardcoded dimension, and I'm looking for some more flexible solution. I tried also RelativeLayout with android:layout_toRightOf="@id/search_view" with no luck.


Solution

  • After considering the suggestions from comments, many googling and testing succeeded in obtaining the desired effect. I'm not proud of this solution but it works, it's not too complicated and should be enough for this case.

    In resume what I did:

    1. Placed SearchView with custom "add item" button in customView of ActionBar.
    2. Removed collapseActionView and android:actionLayout from search item in menu.xml
    3. Collapsing/expanding SearchView programmatically.

    Some code to better understand what I did. Maybe this can be useful for someone.

    menu.xml

    <item
        android:id="@+id/menu_search"
        android:icon="@drawable/action_search"
        android:showAsAction="always"
        android:title="@string/search" />
    
    // ... other menu items
    

    actionbar_search.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="right"
        android:orientation="horizontal">
    
        <com.actionbarsherlock.widget.SearchView
            android:id="@+id/search_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:iconifiedByDefault="false"
            android:queryHint="@string/search_hint"
            android:visibility="invisible" />
    
        <ImageButton
            android:id="@+id/add_item"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            style="@style/Widget.Sherlock.ActionButton"
            android:src="@drawable/content_new"
            android:title="@string/add_item" />
    
    </LinearLayout>
    

    MainActivity.java

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // ...
        actionBar.setCustomView(R.layout.actionbar_search);
        actionBarCustomView = ab.getCustomView();
        searchView = ((SearchView) actionBarCustomView.findViewById(R.id.search_view));
        searchView.setOnCloseListener(new SearchView.OnCloseListener() {
            @Override
            public boolean onClose() {
                searchView.setVisibility(View.INVISIBLE);
                return false;
            }
        });
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            // ...
            case R.id.menu_search:
                if (searchView.getVisibility() == View.VISIBLE) {
                    searchView.setIconified(true);
                    searchView.setVisibility(View.INVISIBLE);
                } else {
                    searchView.setMaxWidth(abCustomView.getWidth() - addButton.getWidth());
                    searchView.setVisibility(View.VISIBLE);
                    searchView.setIconified(false);
                }
                break;
            // ...
        }
        return true;
    }
    
    @Override
    public void onBackPressed() {
    
        if (searchView.getVisibility() == View.VISIBLE) {
            searchView.setIconified(true);
            searchView.setVisibility(View.INVISIBLE);
            return;
        }
    
        // ...
    }