20

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.

N J
  • 27,217
  • 13
  • 76
  • 96
Rafal Gałka
  • 1,022
  • 1
  • 10
  • 16

4 Answers4

9

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;
    }

    // ...
}
N J
  • 27,217
  • 13
  • 76
  • 96
Rafal Gałka
  • 1,022
  • 1
  • 10
  • 16
  • Hi, I have tried your above solution but it is not working at all. In fact I am not able to see any of the action item. – AndoAiron Apr 11 '13 at 10:37
  • Can you post fragments of your code (eg. as gist)? I spent few days figuring it out and testing, think I can help. – Rafal Gałka Apr 12 '13 at 11:14
  • where should I post my code fragment ?? I can't post my problem code here as a comment. Also, could you please help me to achieve this : http://stackoverflow.com/questions/15947557/sherlockactionbar-with-autocompletetextview-and-other-items?noredirect=1#comment22723847_15947557 – AndoAiron Apr 15 '13 at 06:07
  • You can use, for example https://gist.github.com/ for posting code fragments and paste link here. If I find some time today I will try to help in your question. – Rafal Gałka Apr 16 '13 at 08:13
  • 1
    Just so you know that its much easier to achieve this by using RelativeLayout inside actionbar_search.xml and simply give imageButton alignParentRight=true. Also you need to add android:layout_toLeftOf="@+id/add_item" to your SearchView. Just tested, works just fine – AndroidGecko Jun 20 '13 at 10:28
2

You can do it only using yourmenu.xml.

Set your other menu icon to always show as an action. Your menu.xml should look like this:

<item
    android:id="@+id/menu_search"
    android:actionLayout="@layout/actionbar_search"
    android:icon="@drawable/action_search"
    android:showAsAction="always|collapseActionView"
    android:title="@string/search"
/>
<item
    android:id="@+id/your_other_menu_id"
    android:showAsAction="always"
    android:icon="@android:drawable/your_other_menu_ic"
 />
JPMagalhaes
  • 3,611
  • 1
  • 25
  • 26
  • Tried this approach. As I mentioned there are other menu items and all of them overflows to bottom actionbar. And I need this one add action always placed in right top corner. – Rafal Gałka Mar 15 '13 at 07:35
  • 1
    The detail in this case is the split action bar, not the collapsable search view. Check the link bellow. It is not possible to set this behavior using native objects. You'll need to create your own customized action bar. http://stackoverflow.com/questions/8571754/android-split-action-bar-with-action-items-on-the-top-and-bottom – JPMagalhaes Mar 15 '13 at 21:34
  • Thanks for advice, but I already tried this one too. Custom ActionBar gives me custom view when SearchView is collapsed. Then I have my single button at the top bar and those form menu.xml at the bottom. The problem is when SearchView is expanded. I need to force it to fill all available space between app icon and single action item. I tried understand what is happening in `onMeasure()` of SearchView class but not exactly understand what I can do with this, and if it is, at all, a right direction. Any help would be appreciated. – Rafal Gałka Mar 15 '13 at 22:59
  • Have you tried to create your own action view class? May be you can simply extend SearchView class but I'm not sure. In resume, what you can do is: 1. Create a class that implements CollapsibleActionView (may be extending SearchView); Where you can implement onActionViewExpanded() adding a button for your menu item after the TextEdit. 2. set this class as the action view class on your menu item: android:actionViewClass="your.package.YourSearchView" – JPMagalhaes Mar 17 '13 at 01:53
1

Simply you can do it like this

@Override
public boolean onCreateOptionsMenu(Menu menu) {
     getMenuInflater().inflate(R.menu.main, menu);
     MenuItem searchItem = menu.findItem(R.id.action_search);
     searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
     searchView.setIconified(true); //to be opened collapsed
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()){

        case R.id.action_search:
            searchView.setIconified(false);// to Expand the SearchView when clicked
            return true;
    }    
    return false;
}

And at search item in menu.xml make

showAsAction="always"

Note: I am using android.support.v7.widget.SearchView but in your case it doesn't matter

Salma
  • 290
  • 2
  • 7
0

Just a change menu xml. showaction prefix to your app name

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" >

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

</menu>
nadafafif
  • 561
  • 6
  • 10