ActionBarのTabの高さは48dpまで(JellyBean以降)

たとえば、アクションバーのタブの高さを設定したくて、こんなコードを書いたとする。

<style name="Theme.MyTheme" parent="android:style/Theme.Holo.Light">
    <item name="android:actionBarTabStyle">@style/MyActionBarTabStyle</item>
    <item name="android:actionBarSize">100dp</item>
</style>

<style name="MyActionBarTabStyle" parent="android:style/Widget.Holo.Light.ActionBar.TabView">  
    <item name="android:height">100dp</item>
</style>

タブの高さが最大48dpにしかならない。


JellyBean以降、targetSdkVersionと画面向きによってタブの高さの制限がある。

targetSdkVersion 画面向き タブの高さ
JellyBean以降 縦画面 最大48dp
横画面 制限なし
ICS以前 縦画面 最大48dp
横画面 最大48dp

縦画面(portscape)
f:id:incesticide:20140413205403p:plain

横画面(landscape)
f:id:incesticide:20140413205416p:plain

横画面は、アクションバーと一体化するから制限がなくなる・・・のだろうか。

※執筆時点では Android Developers に言及なし

説明

「ActionBar のタブの高さは 48dp 以上にできない」(by yanzm)

↑の記事の続き。


http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/base/core/java/com/android/internal/widget/ScrollingTabContainerView.java#65

    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;
    }

hasEmbeddedTabs()がfalseになると、R.dimen.action_bar_stacked_max_heightが設定される。このhasEmbeddedTabs()は何者か?

    public boolean hasEmbeddedTabs() {
        final int targetSdk = mContext.getApplicationInfo().targetSdkVersion;
        if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
            return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs);
        }

        // The embedded tabs policy changed in Jellybean; give older apps the old policy
        // so they get what they expect.
        return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs_pre_jb);
    }

targetSdkVersionを判定する。

JellyBean以降の場合
R.bool.action_bar_embed_tabs
ICS以前の場合
R.bool.action_bar_embed_tabs_pre_jb


http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/base/core/res/res/values-port/bools.xml#18

    <bool name="action_bar_embed_tabs">false</bool>
  • action_bar_embed_tabs = false(縦画面の場合)

http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/base/core/res/res/values/bools.xml#22

    <bool name="action_bar_embed_tabs">true</bool>
    <bool name="action_bar_embed_tabs_pre_jb">false</bool>
  • action_bar_embed_tabs = true(横画面の場合)
  • action_bar_embed_tabs_pre_jb = false


targetSdkVersionがJB以降、かつ、横画面以外は制限あり。

結論

  • Toolbar を使う

https://developer.android.com/reference/android/support/v7/widget/Toolbar.html

Sep 11 2016 追記
この記事を書いた当時にはありませんでしたが、Toolbar が公開された今となっては、現在はほぼこれ一択。
記事を放置している間にも、この記事にアクセスする方が多く、追記することに。
古くなった記事を、破棄するか、追記するか、悩みどころではある。

  • 諦める

ユーザビリティに影響するならともかく、単なる拘りだけならば。

  • アクションバーにカスタムビューを配置する

タブじゃなければ、アクションバーの高さは設定できる。

http://developer.android.com/reference/android/app/ActionBar.html#setCustomView(int)

TabListenerに依存していた場合は、設計からやりなおす覚悟で。

  • アクションバーをやめる

設計からやりなおし。

※ただし、TabActivityやTabHostを使ってはならない(Obsoleted)

参考

困ったときにググると、たいていyanzmさんの記事がヒットします。
とっても素晴らしい本の著者でもあります。お世話になってます。

関連記事

レイアウトに関するノウハウを物語っぽくまとめた記事。