Как получить высоту ActionBar?

190

Я пытаюсь получить высоту ActionBar(используя Шерлока) каждый раз, когда создается действие (особенно для обработки изменений конфигурации при вращении, когда высота ActionBar может измениться).

Для этого я использую метод, ActionBar.getHeight()который работает только тогда, когда ActionBarпоказано.

Когда первое действие создается в первый раз, я могу позвонить getHeight()в onCreateOptionsMenuобратный вызов. Но этот метод не вызывается после.

Поэтому мой вопрос: когда я могу вызвать getHeight () и быть уверенным, что он не вернет 0? Или, если это невозможно, как я могу установить высоту панели действий?

znat
источник

Ответы:

419

Хотя ответ @ 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());
}

Котлин :

val tv = TypedValue()
if (requireActivity().theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
    val actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, resources.displayMetrics)
}
Энтони
источник
13
большая помощь !! но откуда вы найдете все такие вещи!
Викки
5
Как правило, из исчерпывающего поиска в Google или дружественных по руководству разработчика. Я думаю, что последний в этом случае, но это было какое-то время.
Энтони
1
Можем ли мы изменить размер панели действий только для определенного вида деятельности?
Сударшан Бхат
Это сработало для меня в обоих случаях: (i) onCreateView и (ii) onConfigurationChanged. Спасибо!
Марсело Ногути
5
«android.R.attr.actionBarSize» не работает в версии 2.3 для Android, но «R.attr.actionBarSize» работает для всех версий Android. просто используйте «R.attr.actionBarSize» вместо «android.R.attr.actionBarSize», «android.support.v7.appcompat.R.attr.actionBarSize» и т. д.
Натаниэль Джобс
148

В XML вы должны использовать этот атрибут:

android:paddingTop="?android:attr/actionBarSize"
cesards
источник
20
в случае, если вы используете ActionBarCompat "@ измерения / abc_action_bar_default_height"
Али AlNoaimi
10
Спасибо Али Алноаими! В AppCompat v21 имя изменилось на: "@ Dimension / abc_action_bar_default_height_material"
Тони Сералва
5
Как упомянуто ниже @muzikant, для appcompat, если вы хотите использовать его в коде, правильным атрибутом является android.support.v7.appcompat.R.attr.actionBarSize. Если вы хотите использовать его в макете XML android:paddingTop="?attr/actionBarSize". Работает нормально везде.
rpattabi
1
Это решение замечательно, когда вы используете пользовательский XML-каркас.
Tryp
2
Если я хочу использовать этот атрибут, но использовать его с отрицательным отступом. Как я могу это сделать?
Разработчик Tiger
17

Хорошо, я погуглил и попал на этот пост несколько раз, так что я думаю, что было бы хорошо, чтобы его описали не только для Шерлока, но и для appcompat:

Высота панели действий с помощью appCompat

Довольно похоже на описание @Anthony, вы можете найти его с помощью следующего кода (я только что изменил идентификатор ресурса):

TypedValue tv = new TypedValue();

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

Предварительная проблема Sandwitch

Мне нужна была высота панели действий, потому что на устройствах до ICE_CREAM_SANDWITCH мой взгляд был перекрывающим панель действий. Я попытался установить android: layout_marginTop = "? Android: attr / actionBarSize", android: layout_marginTop = "? Attr / actionBarSize", установив перекрытие для view / actionbar и даже фиксированную высоту actionbar с пользовательской темой, но ничего не получалось. Вот как это выглядело:

проблема перекрытия

К сожалению, я обнаружил, что с помощью метода, описанного выше, я получаю только половину высоты (я предполагаю, что панель опций не занята), поэтому для полного исправления isue мне нужно удвоить высоту панели действий, и все выглядит нормально:

исправлено перекрытие

Если кто-то знает лучшее решение (чем удвоение actionBarHeight), я буду рад сообщить мне, так как я пришел из разработки для iOS, и я обнаружил, что большинство вещей в представлении Android довольно сбивают с толку :)

С Уважением,

hris.to

hris.to
источник
Я испытал то же самое при использовании вкладок. Проблема в том, что иногда трудно обнаружить вкладки, а не вкладки, поскольку в некоторых ситуациях некоторые устройства визуально сворачивают вкладки в базовый ActionBar. Так что у меня получилось просто ActionBar.getHeight(). В зависимости от ситуации, это может сработать и для вас.
TalkLittle
Я столкнулся с проблемой, потому что я рассматривал только высоту панели действий, затем я также добавил высоту «панели уведомлений». Это хорошо сработало для меня.
Дарпан
Вы используете FrameLayout и есть layout_gravity="center_vertical"? Измените это на "bottom". Android 2.3 обрабатывает маржу в FrameLaoyut иначе, чем новые андроиды.
Олив
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());
   }
laaptu
источник
Вы можете обернуть первый if с помощью «if (Build.VERSION.SDK_INT> = Build.VERSION_CODES.HONEYCOMB) {}», чтобы избежать ошибок времени выполнения в старых версиях Android.
Marina.Eariel
Для меня com.actionbarsherlock.R.attr.actionBarSizeработал как для Android 2.3, так и для 4.0, так что, похоже, вы можете использовать это независимо от версии Android.
Феликс
13

я думаю, что самый безопасный способ будет:

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
источник
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
"if (true =="? Я думаю, что вы можете удалить "true" ... :)
Android-разработчик
Да, вы правы ... это просто добавлено для ясности
Музикант
Из вашего кода, похоже, не имеет значения, если я использую ABS, во всех версиях выше HONEYCOMB он будет принимать высоту панели действий от android.R.attr.actionBarSize. Это верно ?
AsafK
в любом случае, указать половину панели действий, чтобы скрыть верхнюю часть экрана? stackoverflow.com/questions/27163374/…
Стив
6

Чтобы установить высоту 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"
Birdy
источник
1
Обратите внимание, что высота панели действий меньше в ландшафтном режиме.
Марк Буйкема
Я не рекомендую это, так как actionBarSherlock учитывает многое при определении высоты панели действий. Если вы сделаете это, высота actionBar не будет зависеть от характеристик устройства и, следовательно, не будет выглядеть как стандартная высота для определенных устройств.
Крис Спраг
5

Ява:

    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
источник
5

Если вы используете панель инструментов в качестве панели действий,

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

затем просто используйте layout_height панели инструментов.

int actionBarHeight = toolbar.getLayoutParams().height;
jk7
источник
3

Вы можете использовать эту функцию, чтобы получить высоту панели действий.

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
источник
2

Этот вспомогательный метод должен пригодиться кому-то. Пример: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();
        }
    }
}
Саймон
источник
2

Вы просто должны добавить это.

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
источник
2

Я нашел более общий способ обнаружить это:

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

где ' mainView ' - это корневой вид вашего макета.

Идея в основном состоит в том, чтобы получить Y-позицию главного окна, так как оно установлено прямо под панелью действий (или панелью инструментов).

Альесио Карвалью
источник
2

Высота панели действий зависит от применяемой темы. Если вы используете AppCompatActivity, высота в большинстве случаев будет отличаться от обычной активности.

Если вы используете AppCompatActivity, вы должны использовать R.attr.actionBarSize вместо 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));
    }
Махмуд
источник
2

В xml вы можете использовать? Attr / actionBarSize, но если вам нужен доступ к этому значению в Java, вам нужно использовать следующий код:

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;
    }
Факсриддин Абдуллаев
источник
2

Готовый способ выполнить самый популярный ответ:

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;
}
Зон
источник
2

Вот обновленная версия с Kotlin, которую я использовал, предполагая, что телефон выше, чем Honeycomb:

val actionBarHeight = with(TypedValue().also {context.theme.resolveAttribute(android.R.attr.actionBarSize, it, true)}) {
            TypedValue.complexToDimensionPixelSize(this.data, resources.displayMetrics)
        }
bboyairwreck
источник
1

Если вы используете Xamarin / C #, это код, который вы ищете:

var styledAttributes = Context.Theme.ObtainStyledAttributes(new[] { Android.Resource.Attribute.ActionBarSize });
var actionBarSize = (int)styledAttributes.GetDimension(0, 0);
styledAttributes.Recycle();
Фред
источник
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();
}
Деврадж Сингх
источник
0

Простой способ найти высоту панели действий - из onPrepareOptionMenuметода Activity .

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
           ....
           int actionBarHeight = getActionBar().getHeight());
           .....
    }
Ашиш Джа
источник
0

В javafx (используя Gluon) высота устанавливается во время выполнения или что-то в этом роде. В то время как возможность получить ширину, как обычно, ...

double width = appBar.getWidth();

Вы должны создать слушателя:

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

... И принять самое последнее значение, на которое оно изменилось. Чтобы получить высоту.

Lealo
источник
0

Попробовав все, что там было безуспешно, я случайно обнаружил функциональный и очень простой способ получить высоту панели действий по умолчанию.

Проверено только в API 25 и 24

C #

Resources.GetDimensionPixelSize(Resource.Dimension.abc_action_bar_default_height_material); 

Ява

getResources().getDimensionPixelSize(R.dimen.abc_action_bar_default_height_material);
Рафаэль Перейра
источник