Jak uzyskać wysokość ActionBar?


190

Próbuję uzyskać wysokość ActionBar(przy użyciu Sherlocka) za każdym razem, gdy tworzone jest działanie (szczególnie do obsługi zmian konfiguracji przy obrocie, w których wysokość ActionBar może się zmienić).

W tym celu używam metody, ActionBar.getHeight()która działa tylko wtedy, gdy ActionBarjest pokazany.

Kiedy pierwsza czynność jest tworzony po raz pierwszy, mogę zadzwonić getHeight()w onCreateOptionsMenuzwrotnego. Ale ta metoda nie jest wywoływana później.

Więc moje pytanie brzmi: kiedy mogę wywołać getHeight () i mieć pewność, że nie zwraca 0? Lub jeśli nie jest to możliwe, jak ustawić wysokość paska ActionBar?

Odpowiedzi:


418

Chociaż odpowiedź @ birdy jest opcją, jeśli chcesz jawnie kontrolować rozmiar ActionBar, istnieje sposób, aby go podciągnąć bez blokowania rozmiaru, który znalazłem w dokumentacji wsparcia. To trochę niezręczne, ale zadziałało dla mnie. Potrzebujesz kontekstu, ten przykład byłby prawidłowy w działaniu.

// 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)
}

13
świetna pomoc !! ale skąd można znaleźć wszystkie takie rzeczy !!
vikky

5
Zasadniczo z wyczerpującego Googlingu lub przemaczania po podręczniku programisty. Myślę, że to drugie w tym przypadku, ale minęło trochę czasu.
Anthony

1
Czy możemy zmienić rozmiar paska akcji tylko dla określonej aktywności?
Sudarshan Bhat

W obu przypadkach zadziałało to dla mnie: (i) onCreateView i (ii) onConfigurationChanged. Dzięki!
Marcelo Noguti

5
„android.R.attr.actionBarSize” nie działa w Androidzie w wersji 2.3, ale „R.attr.actionBarSize” działa we wszystkich wersjach Androida. wystarczy użyć „R.attr.actionBarSize” zamiast „android.R.attr.actionBarSize”, „android.support.v7.appcompat.R.attr.actionBarSize” itp.
Nathaniel Jobs

148

W XML powinieneś użyć tego atrybutu:

android:paddingTop="?android:attr/actionBarSize"

20
w przypadku korzystania z ActionBarCompat „@ dimen / abc_action_bar_default_height”
Ali AlNoaimi

10
Dzięki Ali AlNoaimi! W AppCompat v21 nazwa zmieniła się na: „@ dimen / abc_action_bar_default_height_material”
Tony Ceralva

5
Jak wspomniano poniżej @muzikant, dla appcompat, jeśli chcesz go użyć w kodzie, poprawnym atrybutem jest android.support.v7.appcompat.R.attr.actionBarSize. Jeśli chcesz użyć go w układzie XML android:paddingTop="?attr/actionBarSize". Działa dobrze wszędzie.
rpattabi

1
To rozwiązanie jest wspaniałe, gdy używasz niestandardowej ramki XML.
tryp

2
Jeśli chcę użyć tego atrybutu, ale ujemnego, aby użyć go z ujemnym wypełnieniem. Jak mogę to zrobić?
programista Tiger

17

Ok, przeglądałem go i kilka razy trafiałem do tego postu, więc myślę, że dobrze byłoby opisać nie tylko Sherlocka, ale także appcompata:

Wysokość paska akcji za pomocą appCompat

Całkiem podobny do opisu @Anthony można go znaleźć za pomocą następującego kodu (właśnie zmieniłem identyfikator zasobu):

TypedValue tv = new TypedValue();

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

Problem z przed kanapką

Potrzebowałem wysokości paska akcji, ponieważ na urządzeniach z ICE_CREAM_SANDWITCH mój widok nakładał się na pasek akcji. Próbowałem ustawić android: layout_marginTop = "? Android: attr / actionBarSize", android: layout_marginTop = "? Attr / actionBarSize", ustawienie nakładania się na view / actionbar, a nawet stałą wysokość paska akcji z niestandardowym motywem, ale nic nie działało. Tak to wyglądało:

problem nakładania się

Niestety dowiedziałem się, że dzięki metodzie opisanej powyżej otrzymuję tylko połowę wysokości (zakładam, że pasek opcji nie jest zajęty), więc aby całkowicie naprawić problem, muszę podwoić wysokość paska akcji i wszystko wydaje się w porządku:

zakładka naprawiona

Jeśli ktoś zna lepsze rozwiązanie (niż podwojenie actionBarHeight), z przyjemnością dam mi znać, ponieważ pochodzę z rozwoju iOS i większość rzeczy związanych z widokiem na Androida jest dość myląca :)

Pozdrowienia,

hris.to


Doświadczyłem tego samego podczas korzystania z kart. Problem polega na tym, że czasami trudno jest wykryć karty, a nie karty, ponieważ niektóre urządzenia wizualnie zwiną karty w podstawowy pasek ActionBar w niektórych sytuacjach. Więc to, co zadziałało, jest po prostu ActionBar.getHeight(). W zależności od sytuacji może to również zadziałać.
TalkLittle,

Stawiłem czoła temu problemowi, ponieważ rozważałem tylko wysokość paska akcji, a następnie dodałem również wysokość paska powiadomień. To działało dla mnie dobrze.
Darpan

Czy używasz FrameLayout i masz layout_gravity="center_vertical"? Zmień to na "bottom". Android 2.3 obsługuje marginesy w FrameLaoyut inaczej niż nowsze Androidy.
Oliv

16

@Anthony odpowiedź działa na urządzeniach, które obsługują ActionBari dla urządzeń, które obsługują tylko Sherlock Action Barnastępującą metodę, należy użyć

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

Możesz owinąć pierwszą opcję if jeśli „if (Build.VERSION.SDK_INT> = Build.VERSION_CODES.HONEYCOMB) {}”, aby uniknąć błędów w czasie wykonywania starszych wersji Androida.
Marina.Eariel

Dla mnie com.actionbarsherlock.R.attr.actionBarSizedziałał zarówno na Androida 2.3, jak i 4.0, więc wygląda na to, że możesz z niego korzystać niezależnie od wersji Androida.
Felix

13

myślę, że najbezpieczniejszym sposobem byłoby:

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
w przypadku korzystania z appcompat, dodaj: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 ==”? Myślę, że możesz usunąć „true” ... :)
programista Androida

Tak, masz rację ... to właśnie dodano dla jasności
Muzikant

Z twojego kodu wygląda na to, że nie ma znaczenia, czy używam ABS, we wszystkich wersjach powyżej HONEYCOMB pobierze wysokość paska akcji z android.R.attr.actionBarSize. Czy to jest poprawne ?
AsafK

czy w ogóle należy określić pasek połowy akcji, aby ukryć górę ekranu? stackoverflow.com/questions/27163374/…
Steve

6

Aby ustawić wysokość ActionBar, możesz utworzyć nową, Themetaką jak ta:

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

i ustaw to Themena Activity:

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

1
Zauważ, że wysokość paska akcji jest mniejsza w trybie poziomym.
Mark Buikema

Nie polecam tego, ponieważ actionBarSherlock bierze wiele pod uwagę przy podejmowaniu decyzji o wysokości paska akcji. Jeśli to zrobisz, wysokość paska działań nie będzie oparta na specyfikacji urządzenia, a zatem nie będzie wyglądać jak standardowa wysokość dla niektórych urządzeń.
Chris Sprague

5

Jawa:

    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

5

Jeśli używasz paska narzędzi jako paska działań,

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

następnie po prostu użyj layout_height paska narzędzi.

int actionBarHeight = toolbar.getLayoutParams().height;

3

możesz użyć tej funkcji, aby uzyskać wysokość paska akcji.

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

2

Ta metoda pomocnicza powinna się komuś przydać. Przykład: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

musisz to tylko dodać.

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

2

Znalazłem bardziej ogólny sposób, aby to odkryć:

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

gdzie „ mainView ” to widok główny twojego układu.

Chodzi o to, aby uzyskać pozycję Y mainView, ponieważ jest ona ustawiona bezpośrednio pod paskiem czynności (lub paskiem narzędzi).


2

Wysokość paska akcji różni się w zależności od zastosowanego motywu. Jeśli używasz AppCompatActivity, wysokość będzie w większości przypadków różna od normalnej aktywności.

Jeśli używasz AppCompatActivity , powinieneś użyć R.attr.actionBarSize zamiast 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

W xml możesz użyć? Attr / actionBarSize, ale jeśli potrzebujesz dostępu do tej wartości w Javie, musisz użyć poniższego kodu:

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

Gotowa metoda na spełnienie najpopularniejszej odpowiedzi:

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

Oto zaktualizowana wersja z Kotlin, z której korzystałem, zakładając, że telefon jest wyższy niż Honeycomb:

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

1

Jeśli używasz Xamarin / C #, to jest kod, którego szukasz:

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

Prostym sposobem na znalezienie wysokości paska akcji jest onPrepareOptionMenumetoda działania .

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
           ....
           int actionBarHeight = getActionBar().getHeight());
           .....
    }

0

W javafx (przy użyciu Gluon) wysokość jest ustawiana w czasie wykonywania lub coś podobnego. Chociaż jest w stanie uzyskać szerokość tak jak normalnie ...

double width = appBar.getWidth();

Musisz utworzyć detektor:

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

... I weź najnowszą wartość, którą zmienił. Aby uzyskać wysokość.


0

Po wypróbowaniu wszystkiego, co istnieje, bez powodzenia, znalazłem przez przypadek funkcjonalny i bardzo łatwy sposób na uzyskanie domyślnej wysokości paska akcji.

Testowane tylko w API 25 i 24

DO#

Resources.GetDimensionPixelSize(Resource.Dimension.abc_action_bar_default_height_material); 

Jawa

getResources().getDimensionPixelSize(R.dimen.abc_action_bar_default_height_material);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.