Actionbar Sherlock - tabs won't change in landscape when swiping
Asked Answered
M

2

7

I have a screen which uses ViewPager + actionbar Sherlock tabs. I have a setOnPageChangeListener set on the pager and it does the following:

@Override
public void onPageSelected(final int position) {
    actionBar.setSelectedNavigationItem(position);
}

This works just fine in portrait mode and even in landscape if I only have few tabs and all the tabs are displayed. However if I add few more tabs in landscape, these collapse into a single drop-down widget. When I page through the ViewPager the setSelectedNavigationItem method is executed but now it has no effect on the drop-down selection: it stays at the last selected value. Which is really bad since user is missing a visual clue: tab may say "One" but user is already on page #6.

Is there a way to programmatically change which tab to display based on the position?

P.S. I know why this happens: Here's code from com.android.internal.app.ActionBarImpl:

public void setSelectedNavigationItem(int position) {
    switch (mActionView.getNavigationMode()) {
    case NAVIGATION_MODE_TABS:
        selectTab(mTabs.get(position));
        break;
    case NAVIGATION_MODE_LIST:
        mActionView.setDropdownSelectedPosition(position);
        break;
    default:
        throw new IllegalStateException(
                "setSelectedNavigationIndex not valid for current navigation mode");
    }
}

And when I step through that I can see that the navigation mode is still NAVIGATION_MODE_TABS though tabs are displayed as list. Now - my knee jerk reaction is to put code into onConfigurationChanged to set navigation mode appropriately but shouldn't this happen automatically?

P.P.S. And there's Android bug filed for it already that contains the patch

Menefee answered 5/12, 2012 at 4:58 Comment(0)
M
11

Base on the Android bug I'm referencing in the question (see P.P.S.) here's workaround that indeed works. Just add it to your pager

mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
     {
        @Override
        public void onPageSelected(int position)
        {
           actionBar.getTabAt(position).select();
           ViewParent root = findViewById(android.R.id.content).getParent();
           findAndUpdateSpinner(root, position);
        }

        /**
         * Searches the view hierarchy excluding the content view 
         * for a possible Spinner in the ActionBar. 
         * 
         * @param root The parent of the content view
         * @param position The position that should be selected
         * @return if the spinner was found and adjusted
         */
        private boolean findAndUpdateSpinner(Object root, int position)
        {
           if (root instanceof android.widget.Spinner)
           {
              // Found the Spinner
              Spinner spinner = (Spinner) root;
              spinner.setSelection(position);
              return true;
           }
           else if (root instanceof ViewGroup)
           {
              ViewGroup group = (ViewGroup) root;
              if (group.getId() != android.R.id.content)
              {
                 // Found a container that isn't the container holding our screen layout
                 for (int i = 0; i < group.getChildCount(); i++)
                 {
                    if (findAndUpdateSpinner(group.getChildAt(i), position))
                    {
                       // Found and done searching the View tree
                       return true;
                    }
                 }
              }
           }
           // Nothing found
           return false;
        }
     });
Menefee answered 5/12, 2012 at 20:57 Comment(1)
this solution works for the native ActionBar but doesn't work for the compatibility one (on a Gingerbread emulator). how can this be fixed as well ?Viosterol
B
0

You need to add some code in the ActionBarSherlock library project in file ( ActionBarImpl.java ) see this link

Bluestone answered 5/12, 2012 at 5:46 Comment(2)
The fix you pointed to doesn't work, I just checked it. The code is only called from onConfigurationChanged and but I need selected tab changed when I swipe from page to pageMenefee
If you are using ViewPager than inside its listener you need to explicitly set the selected tab ... This is what I do in one of my project.Bluestone

© 2022 - 2024 — McMap. All rights reserved.