Change Actionbar height on Android JellyBean
Asked Answered
D

3

23

I've been recently developing an Android app, in which i need to have a custom layout and dimension for the tab bar. The way that i did it until now is by using Jake Wharton's ActionBarSherlock library to support pre-HoneyComb Android versions, and by applying a style to the app in which i edit the actionBarSize style item.

Now, I've been testing the app on the Galaxy S3 (with Jellybean on it), and the tab bar height doesn't change anymore according to the actionBarSize value.

So I've started looking through JellyBean's code, and I found this method in the ActionBarPolicy class:

    public int getTabContainerHeight() {
            TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.ActionBar,
               com.android.internal.R.attr.actionBarStyle, 0);
            int height = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
            Resources r = mContext.getResources();
            if (!hasEmbeddedTabs()) {
                // Stacked tabs; limit the height
                height = Math.min(height,
                        r.getDimensionPixelSize(R.dimen.action_bar_stacked_max_height));
            }
            a.recycle();
            return height;
    }

From what i gather in this method, it seems that JellyBean limits the height of the TabBar, when the app is in portrait mode, by setting the tab bar height to the "action_bar_stacked_max_height" dimension value (which is 48dp, in 4.1's /values/dimen.xml file), even though I've set the action bar height in actionBarSize.

I've tried overriding this dimension value, by setting it to my own value in my own dimen.xml file, but i had no luck. It didn't work.

My question:

Do you guys know of a way in which i can override the"action_bar_stacked_max_height" dimen value?

Thank you in advance!

Dredi answered 26/2, 2013 at 20:3 Comment(1)
I also have the same issue. Is there any solution you found for this?Moustache
S
1

it seems to me that it was done on purpose and I don't know why. There are some variables in bools.xml

<bool name="action_bar_embed_tabs">true</bool>
<bool name="action_bar_embed_tabs_pre_jb">false</bool>

The height of embed tabs is limited to 48dip in ActionBarPolicy.java, as you have already mentioned. That's why such behaviour can be seen only in Android JellyBean or higher. I can't find a better solution than to make some java reflection. So here is the code

private void hackJBPolicy() {
    View container = findScrollingTabContainer();
    if (container == null) return;

    try {
        int height = getResources().getDimensionPixelSize(R.dimen.action_bar_height);
        Method method = container.getClass()
                .getDeclaredMethod("setContentHeight", Integer.TYPE);
        method.invoke(container, height);
    } catch (NoSuchMethodException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    } catch (IllegalArgumentException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    } catch (IllegalAccessException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    } catch (InvocationTargetException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    }
}

private View findScrollingTabContainer() {
    View decor = getWindow().getDecorView();
    int containerId = getResources().getIdentifier("action_bar_container", "id", "android");

    // check if appcompat library is used
    if (containerId == 0) {
        containerId = R.id.action_bar_container;
    }

    FrameLayout container = (FrameLayout) decor.findViewById(containerId);

    for (int i = 0; i < container.getChildCount(); i++) {
        View scrolling = container.getChildAt(container.getChildCount() - 1);
        String simpleName = scrolling.getClass().getSimpleName(); 
        if (simpleName.equals("ScrollingTabContainerView")) return scrolling;
    }

    return null;
}

Use the method hackJBPolicy() in your onCreate. Notice that I used ActionBar from appcompat library. Here is the link to the sample project with the use of this workaround.

After all, it seems to me that it would be easier in future to create custom view aligned to the top of the screen instead of using ActionBar in tabs mode if your ui design is a bit far from guidlines.

Sentimentalize answered 4/6, 2014 at 17:52 Comment(2)
Can you please explain how to implement that using standard Action Bar, not from support library? I can't find the resource named R.id.action_bar_container.Huxham
I know this is a very late comment but I'm going to accept st_'s answer, even though it uses reflection (which theoretically slows down the app a bit). But he provides sufficient information in order for one to hack his way past the "JB policy". In the end, I developed my own custom tab bar, as st_ said.Dredi
T
26

Try putting android:actionBarSize and actionBarSize under the Theme you are using, like so:

<style name="Theme.white_style" parent="@android:style/Theme.Holo.Light.DarkActionBar">
        <item name="android:actionBarSize">55dp</item>
        <item name="actionBarSize">55dp</item>
</style> 
Tannertannery answered 27/2, 2013 at 17:29 Comment(3)
Well, it changes the height of the main action bar but it does not affect the height of the tab bar (definitely not on Android 4.2.2).Mikael
seeing the same thing. Doesn't seem to change the height of the tab bar.Ellington
I had it work on the oldest version of jellybean on an emulatorHokanson
A
9

Try using android:height like the following:

<style name="AppActionBar">
    <item name="android:height">50dp</item>
</style>

<style name="MainActivityStyle" parent="@android:style/Theme.Holo">
    <item name="android:actionBarStyle">@style/AppActionBar</item>
</style>
Althing answered 10/12, 2013 at 10:41 Comment(1)
works for the split action bar but not for the second row/stacked bar (tabs)Noles
S
1

it seems to me that it was done on purpose and I don't know why. There are some variables in bools.xml

<bool name="action_bar_embed_tabs">true</bool>
<bool name="action_bar_embed_tabs_pre_jb">false</bool>

The height of embed tabs is limited to 48dip in ActionBarPolicy.java, as you have already mentioned. That's why such behaviour can be seen only in Android JellyBean or higher. I can't find a better solution than to make some java reflection. So here is the code

private void hackJBPolicy() {
    View container = findScrollingTabContainer();
    if (container == null) return;

    try {
        int height = getResources().getDimensionPixelSize(R.dimen.action_bar_height);
        Method method = container.getClass()
                .getDeclaredMethod("setContentHeight", Integer.TYPE);
        method.invoke(container, height);
    } catch (NoSuchMethodException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    } catch (IllegalArgumentException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    } catch (IllegalAccessException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    } catch (InvocationTargetException e) {
        Log.e(LOG_TAG, e.getLocalizedMessage(), e);
    }
}

private View findScrollingTabContainer() {
    View decor = getWindow().getDecorView();
    int containerId = getResources().getIdentifier("action_bar_container", "id", "android");

    // check if appcompat library is used
    if (containerId == 0) {
        containerId = R.id.action_bar_container;
    }

    FrameLayout container = (FrameLayout) decor.findViewById(containerId);

    for (int i = 0; i < container.getChildCount(); i++) {
        View scrolling = container.getChildAt(container.getChildCount() - 1);
        String simpleName = scrolling.getClass().getSimpleName(); 
        if (simpleName.equals("ScrollingTabContainerView")) return scrolling;
    }

    return null;
}

Use the method hackJBPolicy() in your onCreate. Notice that I used ActionBar from appcompat library. Here is the link to the sample project with the use of this workaround.

After all, it seems to me that it would be easier in future to create custom view aligned to the top of the screen instead of using ActionBar in tabs mode if your ui design is a bit far from guidlines.

Sentimentalize answered 4/6, 2014 at 17:52 Comment(2)
Can you please explain how to implement that using standard Action Bar, not from support library? I can't find the resource named R.id.action_bar_container.Huxham
I know this is a very late comment but I'm going to accept st_'s answer, even though it uses reflection (which theoretically slows down the app a bit). But he provides sufficient information in order for one to hack his way past the "JB policy". In the end, I developed my own custom tab bar, as st_ said.Dredi

© 2022 - 2024 — McMap. All rights reserved.