modify actionBar's appearance at runtime

2019-09-09 05:49发布

In my application I use an ActionBar (nether ABS nor the support action bar! minSDK = 14). The user may choose whether to use icon or text-based Tabs. I'm still facing some issues while handling the screen rotation. Basically, I have a customView set on the top (using getActionBar.setCustomView()) in which some text and control elements are placed. In portrait mode everything works fine, but rotating the device messes up my UI.

I'm posting some screenshots to illustrate the issue (icons changed to dummy).

The problem here is that the tabs get stacked, I found no way to force the ActionBar to stay 2-lined. If you know how to do it, I'd be really thankful for a solution.

So based upon the fact the ActionBar will stay single-line in landscape mode, I tried at least to customize the background behind the tab text to match my design and it worked.

The real issue starts with icon mode. Portrait:

enter image description here

Everything's fine here. Rotating the device:

enter image description here

So as you can see, there's NO SPACE for the customView and the tab area to be in one line. But since the android dev team believes their ActionBar is smarter then us, the system totally disregards the lack of space, presses the tabs together and places the customView to the right, causing it to overlap the tabs. This completely messes up my UI, and I'm looking for any possible solution (for some reasons I'm forced to use the ActionBar and not something else).

If you need some code related to setting up the ActionBar, I'll post it, though it's pretty much a default implementation so I think this is irrelevant to the question. I'm asking about some basic ideas how to solve the described issue.

1条回答
叼着烟拽天下
2楼-- · 2019-09-09 06:36

You can use reflection to force the tabs to appear on two-lines in both portrait and landscape mode. ActionBarImpl#setHasEmbeddedTabs(boolean) controls whether the tabs will be embedded (shown as a drop-down list) or not. Through reflection, we'll pass the boolean false to it.

See if the following helps:

ActionBar mActionBar = getActionBar();

// Set navigation mode      
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

// Initialize and add tabs      
for (int i=1; i <= 20; i++) {
    Tab tab = mActionBar.newTab();
    tab.setText("Tab " + i);
    tab.setTabListener(this);
    mActionBar.addTab(tab);
}

Method setHasEmbeddedTabsMethod = null;

try {
    setHasEmbeddedTabsMethod = mActionBar.getClass().
                                    getDeclaredMethod("setHasEmbeddedTabs", 
                                                        boolean.class);
} catch (NoSuchMethodException e1) {
    e1.printStackTrace();
}

setHasEmbeddedTabsMethod.setAccessible(true);

try {
    setHasEmbeddedTabsMethod.invoke(mActionBar, false);
} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}
查看更多
登录 后发表回答