如何获取ActionBar的高度?

215

我正在尝试获取每次创建活动时 ActionBar(使用Sherlock)的高度(特别是处理旋转时ActionBar高度可能会发生变化的配置更改)。

为此,我使用方法 ActionBar.getHeight(),该方法仅在 ActionBar 显示时起作用。

当第一次创建第一个活动时,我可以在 onCreateOptionsMenu 回调中调用 getHeight()。但此方法不会被再次调用。

所以我的问题是,我何时可以调用 getHeight() 并确保它不返回 0 呢? 或者如果不可能,如何设置 ActionBar 的高度?

21个回答

456

虽然@birdy的回答可以让您显式控制ActionBar的大小,但我在支持文档中发现了一种方法,可以将其上移而不锁定大小。这有点棘手,但对我很有效。您需要上下文,此示例在Activity中有效。

// Calculate ActionBar height
TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
{
    int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}

Kotlin

val tv = TypedValue()
if (requireActivity().theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
    val actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, resources.displayMetrics)
}

14
非常有帮助!但你是从哪里找到所有这些东西的呢? - vikky
5
通常是通过详尽的谷歌搜索或者耐心翻阅开发手册获得相关信息。我认为在这种情况下应该是后者,不过已经有一段时间没做了。 - Anthony
1
我们能否仅针对特定活动更改操作栏大小? - Sudarshan Bhat
5
在Android 2.3版本中,"android.R.attr.actionBarSize"无法使用,但是"R.attr.actionBarSize"可以在所有Android版本中使用。只需使用"R.attr.actionBarSize"代替"android.R.attr.actionBarSize"、"android.support.v7.appcompat.R.attr.actionBarSize"等。 - Nathaniel Jobs
2
androidx.appcompat.R.attr.actionBarSize 对于 androidx - Pierre
显示剩余11条评论

159
在 XML 中,您应该使用此属性:
android:paddingTop="?android:attr/actionBarSize"

20
如果你正在使用ActionBarCompat,请使用"@dimen/abc_action_bar_default_height"。 - Ali Alnoaimi
10
感谢Ali AlNoaimi!使用AppCompat v21,名称已更改为:“@dimen/abc_action_bar_default_height_material” - Toni Alvarez
5
如下所述,针对appcompat,如果您想在代码中使用它,则正确的属性是android.support.v7.appcompat.R.attr.actionBarSize。 如果您想在布局xml中使用它,则为android:paddingTop="?attr/actionBarSize"。 在任何地方都可以正常工作。 - rpattabi
1
当您使用自定义XML框架布局时,此解决方案非常出色。 - tryp
2
如果我想使用这个属性,但是希望将它与负填充一起使用,我该怎么做? - Tiger developer
显示剩余6条评论

18

好的,我在谷歌上搜索了一下,多次看到了这篇文章,所以我认为不仅对Sherlock,也对appcompat进行描述会很好:

使用appCompat设置操作栏高度

与@Anthony的描述非常相似,您可以使用以下代码找到它(我只是更改了资源ID):

TypedValue tv = new TypedValue();

if (getActivity().getTheme().resolveAttribute(R.attr.actionBarSize, tv, true))
{
    int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}

问题描述:Pre Sandwitch设备上视图与ActionBar重叠

我需要获取ActionBar的高度,因为在pre ICE_CREAM_SANDWITCH设备上,我的视图会与ActionBar重叠。 我尝试使用 android:layout_marginTop="?android:attr/actionBarSize" 或者 android:layout_marginTop="?attr/actionBarSize" ,将视图/ ActionBar设置为不重叠以及使用自定义主题来固定ActionBar的高度,但都没有奏效。 效果如下所示:

overlap problem

不幸的是,我发现上述方法只能获得ActionBar高度的一半(我假设选项栏不占据位置),因此要完全解决此问题,我需要将ActionBar高度加倍,然后一切都正常了:

overlap fixed

如果有人知道比将ActionBar高度加倍更好的解决方案,请告诉我,因为我来自iOS开发,发现Android视图的大部分内容都很令人困惑 :)

问候,

hris.to


当我使用选项卡时,我也遇到了同样的问题。问题在于有时很难检测出选项卡和没有选项卡之间的区别,因为某些设备在某些情况下会将选项卡视觉上折叠到基本操作栏中。所以对我有效的方法就是使用 ActionBar.getHeight()。根据情况,这个方法可能对你也有用。 - TalkLittle
我遇到了问题,因为我只考虑了ActionBar的高度,然后我也加上了“通知栏”的高度。这对我很有效。 - Darpan
你使用FrameLayout并且有layout_gravity="center_vertical"吗?将其改为"bottom"。Android 2.3处理FrameLayout中的边距与新版本的Android不同。 - Oliv

16

@Anthony 的解答适用于支持 ActionBar 的设备,对于那些仅支持 Sherlock Action Bar 的设备,应使用以下方法。

    TypedValue tv = new TypedValue();
    if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());

    if(actionBarHeight ==0 && getTheme().resolveAttribute(com.actionbarsherlock.R.attr.actionBarSize, tv, true)){
            actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
    }

   //OR as stated by @Marina.Eariel
   TypedValue tv = new TypedValue();
   if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB){
      if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
   }else if(getTheme().resolveAttribute(com.actionbarsherlock.R.attr.actionBarSize, tv, true){
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
   }

你可以将第一个if语句包裹在 "if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {}" 中,以避免在旧版Android上出现运行时错误。 - Marina.Eariel
对我来说,com.actionbarsherlock.R.attr.actionBarSize 在 Android 2.3 和 4.0 上都有效,因此看起来您可以在任何 Android 版本上使用它。 - Felix

14

我认为最安全的方法是:

private int getActionBarHeight() {
    int actionBarHeight = getSupportActionBar().getHeight();
    if (actionBarHeight != 0)
        return actionBarHeight;
    final TypedValue tv = new TypedValue();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
            actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
    } else if (getTheme().resolveAttribute(com.actionbarsherlock.R.attr.actionBarSize, tv, true))
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
    return actionBarHeight;
}

9
如果你正在使用 appcompat,请添加以下内容:else if (true == getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, tv, true)),然后将 actionBarHeight 设置为 TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics()) - Muzikant
3
如果条件为“true ==”,我认为你可以去掉“true”这个词... :) - android developer
是的,你说得对...那只是为了更清晰地表达。 - Muzikant
从你的代码来看,似乎无论我是否使用ABS,在所有高于HONEYCOMB版本的Android系统中,它都会从android.R.attr.actionBarSize获取ActionBar的高度。这是正确的吗? - AsafK
有没有办法指定半个操作栏隐藏在屏幕顶部?https://dev59.com/o4Xca4cB1Zd3GeqPJ41I - Stephen

7

要设置 ActionBar 的高度,您可以创建一个新的 Theme,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<resources>   
    <style name="Theme.FixedSize" parent="Theme.Sherlock.Light.DarkActionBar">
        <item name="actionBarSize">48dip</item>
        <item name="android:actionBarSize">48dip</item> 
    </style> 
 </resources>

将这个主题(Theme)设置给你的Activity

android:theme="@style/Theme.FixedSize"

1
请注意,在横屏模式下,操作栏的高度较小。 - Mark Buikema
我不建议这样做,因为actionBarSherlock在决定操作栏高度时考虑了很多因素。如果你这样做,操作栏的高度就不会基于设备规格,因此在某些设备上看起来不像标准高度。 - Chris Sprague

6

如果你正在使用工具栏作为操作栏,

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

然后只需使用工具栏的layout_height即可。
int actionBarHeight = toolbar.getLayoutParams().height;

5

Java:

    int actionBarHeight;
    int[] abSzAttr;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        abSzAttr = new int[] { android.R.attr.actionBarSize };
    } else {
        abSzAttr = new int[] { R.attr.actionBarSize };
    }
    TypedArray a = obtainStyledAttributes(abSzAttr);
    actionBarHeight = a.getDimensionPixelSize(0, -1);

xml:

    ?attr/actionBarSize

4

以下是我使用 Kotlin 的更新版本,假设手机的版本高于 Honeycomb:

val actionBarHeight = with(TypedValue().also {context.theme.resolveAttribute(android.R.attr.actionBarSize, it, true)}) {
            TypedValue.complexToDimensionPixelSize(this.data, resources.displayMetrics)
        }

3
如果您正在使用Xamarin/C#,那么这就是您要寻找的代码:
var styledAttributes = Context.Theme.ObtainStyledAttributes(new[] { Android.Resource.Attribute.ActionBarSize });
var actionBarSize = (int)styledAttributes.GetDimension(0, 0);
styledAttributes.Recycle();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接