215

I am trying to get the height of the ActionBar (using Sherlock) every time an activity is created (specially to handle configuration changes on rotation where the ActionBar height might change).

For this I use the method ActionBar.getHeight() which works only when the ActionBar is shown.

When the first activity is created for the first time, I can call getHeight() in the onCreateOptionsMenu callback. But this method is not called after.

So my question is when can I call getHeight() and be assured that it doesn't return 0? Or if it is not possible, how can I set the height of the ActionBar ?

znat
  • 13,144
  • 17
  • 71
  • 106

21 Answers21

455

While @birdy's answer is an option if you want to explicitly control the ActionBar size, there is a way to pull it up without locking the size that I found in support documentation. It's a little awkward but it's worked for me. You'll need a context, this example would be valid in an 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)
}
ingh.am
  • 25,981
  • 43
  • 130
  • 177
Anthony
  • 7,638
  • 3
  • 38
  • 71
  • 14
    great help !! but from where you find all such things !! – vikky Apr 24 '13 at 09:46
  • 5
    Generally from exhaustive Googling or drudging thru the developer handbook. I think the latter in this case, but it's been a while. – Anthony Apr 30 '13 at 13:20
  • 1
    Can we change the actionbar size only for a particular activity? – Sudarshan Bhat Jun 03 '13 at 13:54
  • This worked for me in both cases: (i) onCreateView and (ii) onConfigurationChanged. Thanks! – Marcelo Noguti Nov 28 '14 at 13:30
  • I had to call getContext().getTheme()... instead of simply getTheme() – thecoolmacdude Dec 04 '14 at 16:41
  • Hence why I said you need a 'context'. I suggest taking a look at the developer handbook to understand why. – Anthony Dec 04 '14 at 20:57
  • As @muzikant mentioned below, for appcompat, you want to use `android.support.v7.appcompat.R.attr.actionBarSize`. Works fine everywhere. – rpattabi Jun 07 '15 at 11:34
  • There's a reason for why it's so unwieldy if you think about each part in terms of abstract theme attributes and arbitrary device specs. But if you think this is hard, try disambiguating "external storage" files in 4.2+. They're *mounted* not *linked* in three locations. Then when you're done with that if you're on 4.4+ you can suffer the "rich" (google for atrocious) Document API to write to external SD cards. – Anthony Aug 24 '15 at 14:54
  • android.support.v7.appcompat.R.attr.actionBarSize works perfectly for me – jiawen Mar 16 '16 at 03:05
  • 5
    "android.R.attr.actionBarSize" is not working in android version 2.3, but "R.attr.actionBarSize" is working android all version. just use "R.attr.actionBarSize" instead of "android.R.attr.actionBarSize", "android.support.v7.appcompat.R.attr.actionBarSize" and etc. – Nathaniel Jobs May 20 '16 at 03:15
  • Yes, thanks for the updates guys. The support library is a far cry from what it was when this was posted. Using the support attr is definitely the way to go if you support pre-AB Android. – Anthony May 20 '16 at 13:56
  • Only `android.support.v7.appcompat.R.attr.actionBarSize` worked with me on galaxy s3 and everywhere. – Hamzeh Soboh Jan 08 '17 at 14:06
  • Is it possible to get an explanation of what was done. And possibly also how you could do it in javafx? – Lealo Jul 26 '17 at 13:36
  • 1
    We get some number, but it's definitely not the same as the action bar height. – Vijay Kumar Kanta Mar 28 '19 at 09:45
  • 2
    `androidx.appcompat.R.attr.actionBarSize` for androidx – Pierre Aug 06 '19 at 13:13
  • Also notice that the result value is in pixels, so if you want 'dp', you must convert the value using `(int) Math.ceil(pixel / density)` to dp. For example I needed this conversion to pass the result to LayoutParams height. – Masoud Maleki May 05 '22 at 18:26
159

In XML, you should use this attribute:

android:paddingTop="?android:attr/actionBarSize"
Aerilys
  • 1,628
  • 1
  • 16
  • 22
cesards
  • 15,882
  • 11
  • 70
  • 65
18

Ok I was googling around and get to this post several times so I think it'll be good to be described not only for Sherlock but for appcompat also:

Action Bar height using appCompat

Pretty similiar to @Anthony description you could find it with following code(I've just changed resource id):

TypedValue tv = new TypedValue();

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

Pre Sandwitch Problem

I needed action bar height because on pre ICE_CREAM_SANDWITCH devices my view was overlaping action bar. I tried setting android:layout_marginTop="?android:attr/actionBarSize", android:layout_marginTop="?attr/actionBarSize", setting overlap off to view/actionbar and even fixed actionbar height with custom theme but nothing worked. That's how it looked:

overlap problem

Unfortunately I found out that with method described above I get only half of the height(I assume that options bar is not taken in place) so to completely fix the isue I need to double action bar height and everything seems ok:

overlap fixed

If someone knows better solution(than doubling actionBarHeight) I'll be glad to let me know as I come from iOS development and I found most of Android view's stuff pretty confusing :)

Regards,

hris.to

hris.to
  • 6,235
  • 3
  • 46
  • 55
  • I experienced the same thing when using tabs. Problem is it's sometimes hard to detect tabs vs. no tabs, since some devices visually collapse the tabs into the base ActionBar in some situations. So what worked for me is just `ActionBar.getHeight()`. Depending on the situation, that may work for you too. – TalkLittle Jan 05 '14 at 19:12
  • I was facing the issue cuz I was only considering actionbar's height, then I added 'notification bar's' height as well. It worked well for me. – Darpan Jun 24 '15 at 07:13
  • Do you use FrameLayout and have `layout_gravity="center_vertical"`? Change it to `"bottom"`. Android 2.3 handles margin in FrameLaoyut differently than newer androids. – Oliv Sep 16 '15 at 07:19
16

@Anthony answer works for devices that support ActionBar and for those devices which support only Sherlock Action Bar following method must be used

    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());
   }
laaptu
  • 2,963
  • 5
  • 30
  • 49
  • You could wrap the first if with "if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {}" to avoid runtime errors on older Android versions. – Marina.Eariel Mar 18 '13 at 20:02
  • For me `com.actionbarsherlock.R.attr.actionBarSize` worked for both Android 2.3 and 4.0, so it looks like you can use this regardless of the Android version. – Felix Jul 23 '13 at 05:43
14

i think the safest way would be :

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;
}
android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • 9
    in case you are using appcompat, add the following: `else if (true == getTheme().resolveAttribute( android.support.v7.appcompat.R.attr.actionBarSize, tv, true)) { actionBarHeight = TypedValue.complexToDimensionPixelSize( tv.data,getResources().getDisplayMetrics()); }` – Muzikant Apr 23 '14 at 15:10
  • 3
    "if (true== " ? I think you can remove the "true"... :) – android developer Apr 23 '14 at 16:36
  • Yeah, you are right... that's just added for clarity – Muzikant Apr 23 '14 at 17:07
  • From your code it looks like it doesnt matter if im using ABS, in all versions above HONEYCOMB it will take the actionbar height from android.R.attr.actionBarSize. Is this correct ? – AsafK Oct 24 '14 at 10:16
  • is it anyway to specify the half action bar to hide top of the screen?http://stackoverflow.com/questions/27163374/hide-only-the-action-bar-on-scroll-not-action-bar-tabs – Stephen Dec 01 '14 at 11:37
7

To set the height of ActionBar you can create new Theme like this one:

<?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>

and set this Theme to your Activity:

android:theme="@style/Theme.FixedSize"
znat
  • 13,144
  • 17
  • 71
  • 106
amukhachov
  • 5,822
  • 1
  • 41
  • 60
  • 1
    Do notice that the height of the action bar is smaller in landscape mode. – Mark Buikema Feb 26 '14 at 10:01
  • I don't recommend this since actionBarSherlock takes a lot into account when deciding the actionbar height. If you do this the actionBar height won't be based on device specs and hence won't look like the standard height for certain devices. – Chris Sprague Jun 01 '14 at 01:37
6

If you are using a Toolbar as the ActionBar,

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

then just use the layout_height of the toolbar.

int actionBarHeight = toolbar.getLayoutParams().height;
jk7
  • 1,958
  • 1
  • 22
  • 31
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
TeeTracker
  • 7,064
  • 8
  • 40
  • 46
3

If you're using Xamarin/C#, this is the code you're looking for:

var styledAttributes = Context.Theme.ObtainStyledAttributes(new[] { Android.Resource.Attribute.ActionBarSize });
var actionBarSize = (int)styledAttributes.GetDimension(0, 0);
styledAttributes.Recycle();
Fred
  • 31
  • 2
3

you can use this function to get actionbar's height.

public int getActionBarHeight() {
    final TypedArray ta = getContext().getTheme().obtainStyledAttributes(
            new int[] {android.R.attr.actionBarSize});
    int actionBarHeight = (int) ta.getDimension(0, 0);
    return actionBarHeight;
}
wangzhengyi
  • 856
  • 8
  • 8
3

A ready method to fulfill the most popular answer:

public static int getActionBarHeight(
  Activity activity) {

  int actionBarHeight = 0;
  TypedValue typedValue = new TypedValue();

  try {

    if (activity
      .getTheme()
      .resolveAttribute(
        android.R.attr.actionBarSize,
        typedValue,
        true)) {

      actionBarHeight =
        TypedValue.complexToDimensionPixelSize(
          typedValue.data,
          activity
            .getResources()
            .getDisplayMetrics());
    }

  } catch (Exception ignore) {
  }

  return actionBarHeight;
}
Zon
  • 18,610
  • 7
  • 91
  • 99
3

Here's an updated version with Kotlin I used assuming phone is higher than Honeycomb:

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

This helper method should come in handy for someone. Example: int actionBarSize = getThemeAttributeDimensionSize(this, android.R.attr.actionBarSize);

public static int getThemeAttributeDimensionSize(Context context, int attr)
{
    TypedArray a = null;
    try{
        a = context.getTheme().obtainStyledAttributes(new int[] { attr });
        return a.getDimensionPixelSize(0, 0);
    }finally{
        if(a != null){
            a.recycle();
        }
    }
}
Simon
  • 10,932
  • 50
  • 49
2

you just have to add this.

public int getActionBarHeight() {
        int height;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            height = getActivity().getActionBar().getHeight();
        } else {
            height = ((ActionBarActivity) getActivity()).getSupportActionBar().getHeight();

        }
        return height;
    }
JCDecary
  • 557
  • 1
  • 7
  • 18
2

I found a more generic way to discover it:

  int[] location = new int[2];
  mainView.getLocationOnScreen(location);
  int toolbarHeight = location[1];

where 'mainView' is the root view of your layout.

The idea is basically get the Y position of the mainView as it is set right below the ActionBar (or Toolbar).

Alécio Carvalho
  • 13,481
  • 5
  • 68
  • 74
2

The action bar height differs according to the applied theme. If you're using AppCompatActivity the height will be different in most of cases from the normal Activity.

If you're using AppCompatActivity you should use R.attr.actionBarSize instead of android.R.attr.actionBarSize

public static int getActionBarHeight(Activity activity) {
        TypedValue typedValue = new TypedValue();

        int attributeResourceId = android.R.attr.actionBarSize;
        if (activity instanceof AppCompatActivity) {
            attributeResourceId = R.attr.actionBarSize;
        }

        if (activity.getTheme().resolveAttribute(attributeResourceId, typedValue, true)) {
            return TypedValue.complexToDimensionPixelSize(typedValue.data, activity.getResources().getDisplayMetrics());
        }

        return (int) Math.floor(activity.getResources()
                .getDimension(R.dimen.my_default_value));
    }
Mahmoud
  • 2,683
  • 1
  • 30
  • 32
2

In xml, you can use ?attr/actionBarSize, but if you need access to that value in Java you need to use below code:

public int getActionBarHeight() {
        int actionBarHeight = 0;
        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 {
            actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,
                    getResources().getDisplayMetrics());
        }
        return actionBarHeight;
    }
Fakhriddin Abdullaev
  • 4,169
  • 2
  • 35
  • 37
1
The action bar now enhanced to app bar.So you have to add conditional check for getting height of action bar.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   height = getActivity().getActionBar().getHeight();
 } else {
  height = ((ActionBarActivity) getActivity()).getSupportActionBar().getHeight();
}
Devraj Singh
  • 447
  • 4
  • 6
0

A simple way to find actionbar height is from Activity onPrepareOptionMenu method.

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
           ....
           int actionBarHeight = getActionBar().getHeight());
           .....
    }
Harshad Pansuriya
  • 20,189
  • 8
  • 67
  • 95
Ashish Jha
  • 121
  • 1
  • 5
0

In javafx (using Gluon), the height is set at runtime or something like it. While being able to get the width just like normal...

double width = appBar.getWidth();

You have to create a listener:

GluonApplication application = this;

application.getAppBar().heightProperty().addListener(new ChangeListener(){
    @Override
    public void changed(ObservableValue observable, Object oldValue, Object newValue) {
        // Take most recent value given here
        application.getAppBar.heightProperty.get()
    }
});

...And take the most recent value it changed to. To get the height.

Lealo
  • 331
  • 1
  • 3
  • 11
0

After trying everything that's out there without success, I found out, by accident, a functional and very easy way to get the action bar's default height.

Only tested in API 25 and 24

C#

Resources.GetDimensionPixelSize(Resource.Dimension.abc_action_bar_default_height_material); 

Java

getResources().getDimensionPixelSize(R.dimen.abc_action_bar_default_height_material);
Rafael Pereira
  • 321
  • 4
  • 9