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?

znat
źródło

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)
}
Anthony
źródło
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"
cesards
źródło
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

hris.to
źródło
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());
   }
laaptu
źródło
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;
}
programista Androida
źródło
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"
ptak
źródło
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
TeeTracker
źródło
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;
jk7
źródło
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;
}
wangzhengyi
źródło
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();
        }
    }
}
Szymon
źródło
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;
    }
JCDecary
źródło
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).

Alécio Carvalho
źródło
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));
    }
Mahmoud
źródło
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;
    }
Faxriddin Abdullayev
źródło
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;
}
Strefa
źródło
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)
        }
bboyairwreck
źródło
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();
Fred
źródło
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
źródło
0

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

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
           ....
           int actionBarHeight = getActionBar().getHeight());
           .....
    }
Ashish Jha
źródło
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ść.

Lealo
źródło
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);
Rafael Pereira
źródło