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
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;
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With