ActionBar Tab + Spinner(List) navigation at the same time

So I was looking for a solution to this particular problem & saw lots of question regarding this on Stackoverflow, But none came up with a solution that works. After several hours of research I managed to find a way to do this.

The idea is very simple. There’s a title bar just beside the small icon in the ActionBar. We are going to replace that title bar (programmatically) with our spinner. So, unlike the “actionLayout” solution, it stays on the left.

device-2014-01-21-011948
device-2014-01-21-012012

Let’s first create a layout file that contains the spinner.

File: spinner_layout.xml

<Spinner xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

And now the fun part…

public class MyActivity  extends SherlockActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        
        ActionBar actionBar = getSupportActionBar(); 
        
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // you wanted this, right?    
        
        int titleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
        
        // If you're using sherlock, in older versions of android you are not supposed to get a reference to android.R.id.action_bar_title, So here's little hack for that.
        if (titleId == 0) {
            titleId = com.actionbarsherlock.R.id.abs__action_bar_title;
        }
        
        View titleView = findViewById(titleId);

        // attach listener to this spinnerView for handling spinner selection change
        Spinner spinnerView = (Spinner) getLayoutInflater().inflate(R.layout.spinner_layout, null); 
        
        //source of ViewGroupUtils class is given at the end of this post.
        ViewGroupUtils.replaceView(titleView, spinnerView);
        
    }
}

And voila!

But…

At this point you will probably get black text on black background. So lets change some colors.

Here’s the source of my style.xml, feel free to change.

<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <style name="AppBaseTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
        
    </style>
    
    <style name="textApearanceActionBar" parent="@style/TextAppearance.Sherlock.Widget.TextView.SpinnerItem">
        <item name="android:textColor">@android:color/white</item>
    </style>
    
     <style name="spinnerItemStyle" parent="@android:style/Widget.Holo.TextView.SpinnerItem">
       <item name="android:textAppearance">@style/textApearanceActionBar</item>  
	   <item name="android:gravity">center_vertical</item>   
    </style>

   <style name="AppTheme" parent="AppBaseTheme">
	    <item name="android:spinnerItemStyle">@style/spinnerItemStyle</item>
	    <item name="android:spinnerDropDownItemStyle">@style/spinnerItemStyle</item>
    </style>

    <style name="ActionBarSpinnerStyle" parent="@style/Widget.Sherlock.Spinner.DropDown.ActionBar">
       
    </style>
    
    
</resources>

We’ll use ActionBarSpinnerStyle for styling the spinner. It only changes the black arrow to gray. We need to modify the activity theme to change the spinner text color from black to white. We can do this by applying AppTheme(from above file) to the related activity.

Now, let’s update the spinner_layout.xml file one more time:
File: spinner_layout.xml

<Spinner xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    style="@style/ActionBarSpinnerStyle"
    android:entries="@array/spinner_items"
 />

in strings.xml, let’s add following lines:

 <string-array name="spinner_items">
        <item>Dhaka</item>
        <item>Chittagong</item>
 </string-array>

File: ViewGroupUtils.java
courtesy of @britzl

public class ViewGroupUtils {

    public static ViewGroup getParent(View view) {
        return (ViewGroup)view.getParent();
    }

    public static void removeView(View view) {
        ViewGroup parent = getParent(view);
        if(parent != null) {
            parent.removeView(view);
        }
    }

    public static void replaceView(View currentView, View newView) {
        ViewGroup parent = getParent(currentView);
        if(parent == null) {
            return;
        }
        final int index = parent.indexOfChild(currentView);
        removeView(currentView);
        removeView(newView);
        parent.addView(newView, index);
    }
}

Comments

  • Awesome, many thanks for this would have taken me days to figure this one out! Thanks LOADS! Peace and Love.

    NinjaMasterMarch 7, 2014
    • you’re welcome.

      Shamim HasnathMarch 15, 2014
  • In the style.xml
    Here are two name that my project don’t have?

    “@style/TextAppearance.Sherlock.Widget.TextView.SpinnerItem”
    “@style/Widget.Sherlock.Spinner.DropDown.ActionBar”

    I have tried to find the Sherlock library, but manu extra errors appear.
    How can I solve this?
    At this moment, the arrow of the spinner is black and the background of the expanded part of the spinner is white.
    Thanks.

    JackyApril 8, 2014
    • I’ve used Sherlock 4.2. Please check with this version. Another way could be copying these two styles from Sherlock library to your project style files.

      Shamim HasnathApril 10, 2014
  • Thank you. It’s works good.

    temna_nichMay 19, 2014
    • you’re welcome.

      Shamim HasnathMay 19, 2014
  • Great fix! But how do I put the spinner on second tab only?

    AimanMay 28, 2014
    • you’ve reference to both “titleView” and “spinnerView”, now you can just replace one by other when you’re on second tab and get it back (replace again) on first tab.

      Shamim HasnathMay 30, 2014
      • But, it would be helpful if you could provide the source code too :) Thanks anyway.

        AimanJune 3, 2014
  • awesome works bro. Thanks for share with us.

    I want to add the spinner to menu button/icon on right side of the Action bar(Sherlock) ; not the app title bar. I already use tab navigation. Can you please guide me.

    Shihab the gameJune 5, 2014
  • Awesome, thanks a lot.

    HasanJune 11, 2014
  • great job! the way you explained is so easy!

    i wish to change style but i don’t want to use sherlock library, how can i do it? i have tried, but there’s something i doing wrong because it’s not working!

    thanks!

    MaripuriJune 27, 2014
  • Many thanks for the tutorial. This one is really great!!! Helped me a lot.

    Reaz Murshed MasudJune 28, 2014
    • you’re welcome.

      Shamim HasnathJune 30, 2014
  • Thanks, but how can i use it without Sherlock, i mean instead of sherlock use default ActionBar?
    also it would be great if there is a project file in github.
    thanks again :)

    novaAugust 28, 2014
  • very nice

    rajuFebruary 27, 2015
  • Hello,

    Thanks for this code, but for some reason this doesn`t work with my current set up. Could you perhaps take a look at my Stackoverflow post? http://stackoverflow.com/questions/31490895/placing-a-spinner-into-a-specific-fragments-toolbar

    Maybe you could drop me an e-Mail and tell me why I can not get it to work?

    Thanks!

    BaviloJuly 19, 2015
  • hi i want do like that but i does not know what is SherlockActivity

    vikramNovember 18, 2015

Leave a Reply