Wysokość paska stanu w systemie Android


332

Jaka jest wysokość paska stanu w Androidzie? Czy zawsze jest tak samo?

Z moich pomiarów wynika, że ​​jest to 25dp, ale nie jestem pewien, czy ma taką samą wysokość na wszystkich platformach.

(Chcę to wiedzieć, aby poprawnie zaimplementować przejście zanikania z działania, które nie ma paska stanu na takie, które ma)


Jeśli wykonasz przenikanie, nie będziesz musiał znać wysokości paska stanu.
stealthcopter

2
Potrzebuję tego, ponieważ niektóre elementy są wyśrodkowane w układzie i chciałbym, aby przenikały się nawzajem.
hpique

możliwy duplikat wysokości paska stanu?
molnarm

Odpowiedzi:


363

na to pytanie odpowiedziano wcześniej ... Wysokość paska stanu?

Aktualizacja ::

Obecna metoda:

ok, wysokość paska stanu zależy od rozmiaru ekranu, na przykład w urządzeniu o rozmiarze ekranu 240 x 320 wysokość paska stanu wynosi 20px, w przypadku urządzenia o rozmiarze ekranu 320 x 480 wysokość paska stanu wynosi 25px, dla urządzenie o rozdzielczości 480 x 800 wysokość paska stanu musi wynosić 38 pikseli

więc polecam użyć tego skryptu, aby uzyskać wysokość paska stanu

Rect rectangle = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
int statusBarHeight = rectangle.top;
int contentViewTop = 
    window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight= contentViewTop - statusBarHeight;

   Log.i("*** Elenasys :: ", "StatusBar Height= " + statusBarHeight + " , TitleBar Height = " + titleBarHeight); 

(stara metoda), aby uzyskać wysokość paska stanu w onCreate()metodzie działania, użyj tej metody:

public int getStatusBarHeight() { 
      int result = 0;
      int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
      if (resourceId > 0) {
          result = getResources().getDimensionPixelSize(resourceId);
      } 
      return result;
} 

Nie dokładnie. Pytam również, czy mogę założyć, że pasek stanu ma tę samą wysokość we wszystkich urządzeniach.
hpique

16
Lub użyć dip? Jeśli zawsze ma 25 dip, kod nie jest potrzebny.
hpique

8
nie możesz założyć, że zawsze wynosi 25dp (sprawdź wysokość np. przy pożarze ognia).
DallinDyer

1
Nie działa w runnable przekazanym do view.post () w onCreate () - zwraca 0
Ixx

4
window.getDecorView().getWindowVisibleDisplayFrame(rectangle)nie jest poprawnym sposobem uzyskania wysokości paska stanu, jeśli jesteś w trybie wielu okien + obrót pionowy + drugie okno. Otrzymasz ogromną wartość (w tym 1. wysokość).
Tuan Chau,

211

Ze wszystkich próbek kodu, których użyłem, aby uzyskać wysokość paska stanu, jedyny, który wydaje się działać w onCreatemetodzie an Activityto:

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

Najwyraźniej rzeczywista wysokość paska stanu jest przechowywana jako zasób Androida. Powyższy kod można dodać do ContextWrapperklasy (np. An Activity).

Znaleziono pod adresem http://mrtn.me/blog/2012/03/17/get-the-height-of-the-status-bar-in-android/


Zamiast na stałe go kodować, lepiej obliczać dynamicznie. Powyższa metoda działała dla mnie!
alchemik

nie powinieneś zamiast tego używać getDimension (...)?
programista Androida

6
Słowo ostrzeżenia - to nie działa na wszystkich urządzeniach. Np. W Transformer TF201 (jak również TF101, TF300 i niektórych innych urządzeniach) wysokość jest zgłaszana jako 25, gdzie nie ma paska stanu.
Błażej Czapp

4
W oparciu o powyższe komentarze wydaje mi się, że kod mówi ci, jaka jest wysokość paska stanu na danym urządzeniu - a nie jaka jest na konkretnej aktywności (która może nie mieć paska stanu).
oszołomiony

w XML można użyć zasobu dimen „@android: dimen / status_bar_height”. <! - Wysokość paska stanu zdefiniowanego w źródłowym pliku systemu Android -> <dimen name = "status_bar_height"> 24dp </dimen>. Ale nie możesz bezpośrednio odwoływać się do tego w swoim projekcie aplikacji. Musisz więc użyć kodu.
Tshunglee,

48

Na urządzeniach MDPI pasek stanu ma 25px. Możemy użyć tego jako podstawy i pomnożyć go przez gęstość (zaokrągloną w górę), aby uzyskać wysokość paska stanu na dowolnym urządzeniu:

int statusBarHeight = Math.ceil(25 * context.getResources().getDisplayMetrics().density);

Dla porównania: ldpi = .75, mdpi = 1, hdpi = 1,5, xhdpi = 2


6
To jest poprawna dla urządzeń, które mają pasek stanu. Zauważ, że ponieważ powyższe zostało napisane, stało się prawdą, że nie wszystkie urządzenia będą miały takie urządzenie. W szczególności urządzenia z systemem ICS mogą mieć połączony pasek stanu / nawigacji u dołu i wcale u góry. W takim przypadku, dla większości celów programowania, chciałbyś przypisać zero do paska stanu, ale powyższe sformułowanie dałoby ci niezerową wielkość.
Carl

1
Również wartość 25px nie jest poprawna dla wszystkich urządzeń mdpi. Może się różnić w zależności od poziomu interfejsu API. Na przykład urządzenie emulujące tablet 10.1 WXGA zgłasza 25 pikseli przy API 16 i 19, ale 24
pikseli

48

Zakodowanie wielkości lub użycie odbicia w celu uzyskania wartości status_bar_heightjest uważane za złą praktykę. Chris Banes mówił o tym w Droidcon w Nowym Jorku . Zalecanym sposobem uzyskania rozmiaru paska stanu jest użycie OnApplyWindowInsetsListener :

myView.setOnApplyWindowInsetsListener { view, insets -> {
  val statusBarSize = insets.systemWindowInsetTop
  return insets
}

Zostało to dodane w API 20 i jest również backportowane przez ViewAppCompat .


To jest najdokładniejsza odpowiedź dzisiaj
keith

dla mnie to strzela tylko raz, jeśli mam fragmenty za pomocą dolnej nawigacji. Jeśli ponownie wymienię fragment, ten detektor nie zostanie wywołany, czy istnieje również moduł pobierający zgodność?
urSus

74
A jednak ten interfejs API jest okropny, ponieważ liczba WTF / Gotchas za scenami jest ogromna. Można by pomyśleć, że możesz to zrobić z dowolnym widokiem, ale nie, musisz przesłonić pewne rzeczy i upewnić się, że TY przekazujesz swoje wstawki swoim dzieciom (??), ponieważ NIEKTÓRE grupy widokowe zrobią (materiał projektowy), a WSZYSTKIE INNE nie ( układ liniowy? ConstraintLayout? cześć?). Zamiast systemu posiadającego Window.getStatusBarSize ()… musimy SUBSKRYBOWAĆ WSTĘPNĄ SŁUCHAWKĘ… idź do domu Android, jesteś pijany. Po prostu zakoduj rozmiar, dopóki Google się nie obudzi, jesteśmy w 2018 roku. Mam nadzieję, że Chris Banes zobaczy ten dzień…
Martin Marconcini,

W moim przypadku nie jest zwolniony. Położyłem to Activity # onCreated. Czy zrobiłem coś złego? Dodatkowo, dlaczego nie używamy mView.getRootWindowInsets ()?
Adil Aliyev

34

Połączyłem niektóre rozwiązania razem:

public static int getStatusBarHeight(final Context context) {
    final Resources resources = context.getResources();
    final int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0)
        return resources.getDimensionPixelSize(resourceId);
    else
        return (int) Math.ceil((VERSION.SDK_INT >= VERSION_CODES.M ? 24 : 25) * resources.getDisplayMetrics().density);
    }

inna alternatywa:

    final View view = findViewById(android.R.id.content);
    runJustBeforeBeingDrawn(view, new Runnable() {
        @Override
        public void run() {
            int statusBarHeight = getResources().getDisplayMetrics().heightPixels - view.getMeasuredHeight();
        }
    });

EDYCJA: Alternatywa dla runJustBeforeBeingDrawn: https://stackoverflow.com/a/28136027/878126


getResources (). getDisplayMetrics (). heightPixels -getActivity (). findViewById (android.R.id.content) .getMeasuredHeight () nie działa w
Androidzie Lolipop

@ ArMo372 Zaktualizowana odpowiedź. Po prostu widok musi najpierw przejść pomiar. Nie musisz używać runJustBeforeBeingDrawn, jeśli już go zdałeś. Użyjesz go tylko w zbyt wczesnych przypadkach.
programista Androida

28

Zgodnie z wytycznymi projektowymi Google ; wysokość paska stanu wynosi 24 dp.

Jeśli chcesz uzyskać wysokość paska stanu w pikselach, możesz użyć poniższej metody:

private static int statusBarHeight(android.content.res.Resources res) {
    return (int) (24 * res.getDisplayMetrics().density);
}

które można wywołać z działania z:

statusBarHeight(getResources());

18
Do czasu Marshmallow było to 25dp. Od Marshmallow jest to 24dp.
Eugen Pechanec,

1
jest to zasadniczo twarde zakodowanie wartości - co nie pozwala na zmiany w projekcie
silikonagle

1
i nie uwzględnia faktu, że pasek stanu nie będzie wyświetlany w tych samych przypadkach
jk7

19

Domyślna wysokość wynosiła 25dp. W Androidzie Marshmallow (API 23) wysokość została zmniejszona do 24dp.

Aktualizacja: należy pamiętać, że od czasów, w których zaczęły się ery wycięć i aparatów wykrawających, używanie statycznej wysokości paska stanu już nie działa. Zamiast tego użyj wstawek okiennych!


1
Słodkie! Właśnie stworzyłem plik dimens.xml specjalnie dla interfejsu API poziomu 23+, w którym ustawiłem wysokość jako 24dp.
Ktoś gdzieś

18

działa to również z linkiem referencyjnym

public int getStatusBarHeight() {
  int result = 0;
  int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
  if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
  }
  return result;
}

13

Mam ten sam problem z koniecznością uzyskania wysokości paska stanu w obiekcie onCreate. To działa dla mnie.

private static final int LOW_DPI_STATUS_BAR_HEIGHT = 19;

private static final int MEDIUM_DPI_STATUS_BAR_HEIGHT = 25;

private static final int HIGH_DPI_STATUS_BAR_HEIGHT = 38;

Wewnątrz onCreate:

DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);

int statusBarHeight;

switch (displayMetrics.densityDpi) {
    case DisplayMetrics.DENSITY_HIGH:
        statusBarHeight = HIGH_DPI_STATUS_BAR_HEIGHT;
        break;
    case DisplayMetrics.DENSITY_MEDIUM:
        statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
        break;
    case DisplayMetrics.DENSITY_LOW:
        statusBarHeight = LOW_DPI_STATUS_BAR_HEIGHT;
        break;
    default:
        statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
}

Widzieć:

http://developer.android.com/reference/android/util/DisplayMetrics.html http://developer.android.com/guide/practices/ui_guidelines/icon_design.html


3
Podoba mi się twój pomysł wykorzystania wartości opartych na gęstości. Jeśli zamierzasz użyć kodu w wielu miejscach (lub użyć innych wartości związanych z gęstością), wolę odciążyć pracę do systemu i przechowywać wartości w zasobie dimen, co powoduje, że zmiana nie jest konieczna. Musisz utworzyć folder wymiarów i plik zasobów dla każdej gęstości. final Resources res = context.getResources (); int statusbarHeight = 0; spróbuj {statusbarHeight = res.getDimensionPixelSize (R.dimen.android_statusbar_height); } catch (NotFoundException e) {}
ProjectJourneyman,

5
Zakodowanie tych wartości jest niebezpieczne, co jeśli zmieni się w późniejszej wersji platformy?
David Snabel-Caunt

Myślę, że zamiast używać na stałe wielkości pikseli (po jednej dla każdej gęstości), lepiej użyć „25dp”.
programista Androida


12

Tak, kiedy próbuję z View, daje wynik 25px. Oto cały kod:

public class SpinActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout lySpin = new LinearLayout(this);
        lySpin.setOrientation(LinearLayout.VERTICAL);       
        lySpin.post(new Runnable()
        {
            public void run()
            {
                Rect rect = new Rect();
                Window window = getWindow();
                window.getDecorView().getWindowVisibleDisplayFrame(rect);
                int statusBarHeight = rect.top;
                int contentViewTop = 
                    window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
                int titleBarHeight = contentViewTop - statusBarHeight;
                System.out.println("TitleBarHeight: " + titleBarHeight 
                    + ", StatusBarHeight: " + statusBarHeight);
            }
        }
    }
}

Powyższy kod działa dla mnie, gdy tworzę nowy układ liniowy, tak jak zrobiłeś powyżej, ale kiedy znajduję viewviewbyid dla lySpin z xml. wtedy zwraca null. nie rozumiem, że tak się zachowuje.
Shaista Naaz

Ponieważ układ nie zna jeszcze swojego rozmiaru w programie onCreate, ponieważ nie został jeszcze narysowany. To, co zwykle robię, to opublikowanie Runnable w wątku interfejsu użytkownika z onCreate, który daje interfejsowi czas na narysowanie się.
Jason Robinson

8

240x320 - 20px

320 x 480 - 25 pikseli

480x800 + - 38px


3
To nie jest już dokładne. Użyj metody pomiaru paska stanu.
Michael

7

Spróbuj tego:

    Rect rect = new Rect();
    Window win = this.getWindow();
    win.getDecorView().getWindowVisibleDisplayFrame(rect);
    int statusBarHeight = rect.top;
    int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
    int titleBarHeight = contentViewTop - statusBarHeight;
    Log.d("ID-ANDROID-CONTENT", "titleBarHeight = " + titleBarHeight );

nie działało to dla mnie w metodzie onCreate dla działania, ale działało, gdy umieściłem go w onClickListener i dał mi pomiar 25


Podejrzewam, że w momencie, w którym testował onCreate (), pasek stanu nie został jeszcze utworzony. Dla kontrastu, kiedy ręcznie kliknął, aby aktywować swój kod onClickListener (), pasek miał już dużo czasu na przemyślenie i był w stanie odzyskać jego rozmiar.
Carl

6

wysokość paska stanu wynosi 24dp w Androidzie 6.0

 <!-- Height of the status bar -->
 <dimen name="status_bar_height">24dp</dimen>
 <!-- Height of the bottom navigation / system bar. -->
 <dimen name="navigation_bar_height">48dp</dimen>

odpowiedź znajdziesz w kodzie źródłowym: frameworks \ base \ core \ res \ res \ values ​​\ dimens.xml


czy istnieje sposób na uzyskanie tego zasobu w naszych plikach XML? @android:dimen/status_bar_heightnie działa dla mnie
Patrick

4

Aby rozwiązać ten problem, zastosowałem podejście kombinowane. Jest to konieczne, ponieważ na tabletach pasek systemowy odejmuje już swoje piksele po wywołaniu metody display.getHeight (). Najpierw sprawdzam, czy pasek systemowy jest obecny, a następnie zbliża się Ben Claytons, który działa dobrze na telefonach.

public int getStatusBarHeight() {
    int statusBarHeight = 0;

    if (!hasOnScreenSystemBar()) {
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
    }

    return statusBarHeight;
}

private boolean hasOnScreenSystemBar() {
    Display display = getWindowManager().getDefaultDisplay();
    int rawDisplayHeight = 0;
    try {
        Method getRawHeight = Display.class.getMethod("getRawHeight");
        rawDisplayHeight = (Integer) getRawHeight.invoke(display);
    } catch (Exception ex) {
    }

    int UIRequestedHeight = display.getHeight();

    return rawDisplayHeight - UIRequestedHeight > 0;
}

3

Dzięki @Niklas +1 jest to właściwy sposób, aby to zrobić.

public class MyActivity extends Activity implements android.support.v4.View.OnApplyWindowInsetsListener {

    Rect windowInsets;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.my_activity);

        View rootview = findViewById(android.R.id.content);

        android.support.v4.View.ViewCompat.setOnApplyWindowInsetsListener(rootview, this);
    }

    android.support.v4.View.WindowInsetsCompat android.support.v4.View.OnApplyWindowInsetsListener.OnApplyWindowInsets(View v, android.support.v4.View.WindowInsetsCompat insets)
    {
        windowInsets = new Rect();
        windowInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
        //StatusBarHeight = insets.getSystemWindowInsetTop();

        //Refresh/Adjust view accordingly

        return insets;
    }
}

Przepraszam, jeśli kod nie jest w 100% poprawny, przekonwertowałem go z Xamarin C #, ale to jest właśnie tego. Działa z wycięciami itp.


2

Przełączone rozwiązanie pełnoekranowe:

To rozwiązanie może wyglądać jak obejście, ale w rzeczywistości bierze pod uwagę to, czy aplikacja działa na pełnym ekranie (czyli ukrywanie paska stanu), czy nie:

Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int barheight = size.y - findViewById(R.id.rootView).getHeight();

W ten sposób, jeśli Twoja aplikacja jest obecnie na pełnym ekranie, barheight będzie równa 0.

Osobiście musiałem to wykorzystać do skorygowania bezwzględnych współrzędnych TouchEvent, aby uwzględnić pasek stanu w następujący sposób:

@Override
public boolean onTouch(View view,MotionEvent event) {
    Display display = getWindowManager().getDefaultDisplay();
    Point size = new Point(); display.getSize(size);
    int YCoord = (int)event.getRawY() - size.y + rootView.getHeight());
}

I to uzyska absolutną współrzędną y, niezależnie od tego, czy aplikacja będzie pełnoekranowa, czy nie.

Cieszyć się


Dzięki, to było jedyne rozwiązanie, które działało dla mnie, gdy wyświetla się też klawiatura Androida.
Thiago Moura,

2

W Androidzie 4.1 i nowszych możesz ustawić zawartość aplikacji tak, aby pojawiała się za paskiem stanu, aby zawartość nie zmieniała się, ponieważ pasek stanu ukrywa się i pokazuje. Aby to zrobić, użyj SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN. Konieczne może być również użycie SYSTEM_UI_FLAG_LAYOUT_STABLE, aby pomóc aplikacji zachować stabilny układ.

Gdy zastosujesz to podejście, Twoim obowiązkiem jest upewnić się, że krytyczne części interfejsu aplikacji (na przykład wbudowane elementy sterujące w aplikacji Mapy) nie zostaną zakryte przez paski systemowe. Może to spowodować, że Twoja aplikacja będzie bezużyteczna. W większości przypadków można sobie z tym poradzić, dodając atrybut android: fitsSystemWindows do pliku układu XML, ustawiony na wartość true. Dostosowuje to dopełnienie nadrzędnej grupy ViewGroup, aby pozostawić miejsce dla okien systemu. Jest to wystarczające dla większości aplikacji.

W niektórych przypadkach może być jednak konieczne zmodyfikowanie domyślnego dopełnienia, aby uzyskać pożądany układ aplikacji. Aby bezpośrednio manipulować układem zawartości w stosunku do pasków systemowych (które zajmują przestrzeń zwaną „wstawkami zawartości” okna), należy przesłonić fitSystemWindows (wstawki Rect). Metoda fitSystemWindows () jest wywoływana przez hierarchię widoku, gdy zmieniają się wstawki zawartości okna, aby umożliwić odpowiednie dostosowanie zawartości okna. Przesłaniając tę ​​metodę, możesz obsługiwać wstawki (a więc i układ aplikacji) w dowolny sposób.

formularz: https://developer.android.com/training/system-ui/status.html#behind


1

Jeśli znasz dokładnie rozmiar VS wysokość

lubić

na przykład w urządzeniu o rozmiarze ekranu 320 x 480 wysokość paska stanu wynosi 25 pikseli, w przypadku urządzenia o rozdzielczości 480 x 800 wysokość paska stanu musi wynosić 38 pikseli

możesz po prostu uzyskać szerokość widoku / rozmiar ekranu, wystarczy użyć instrukcji if else, aby uzyskać wysokość paska stanu


Z mojego doświadczenia wynika, że ​​wysokość opiera się raczej na gęstości niż na rozmiarze ekranu. Oczywiście sama gęstość jest zazwyczaj związana z rozmiarem ekranu, więc istnieje związek pośredni. Na przykład mój stary Moto Droid ma ekran 480 x 854 (zamiast 480 x 800), a pasek stanu ma również wysokość 38 pikseli.
Carl

Wynaleźli do tego dp (piksele niezależne od gęstości)
Roel

1

Powodem, dla którego najlepsza odpowiedź nie działa dla niektórych osób, jest to, że nie można uzyskać wymiarów widoku, dopóki nie będzie on gotowy do renderowania. Użyj a, OnGlobalLayoutListeneraby uzyskać wspomniane wymiary, kiedy faktycznie możesz:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
    decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= 16) {
                decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                // Nice one, Google
                decorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
            Rect rect = new Rect();
            decorView.getWindowVisibleDisplayFrame(rect);
            rect.top; // This is the height of the status bar
        }
    }
}

To najbardziej niezawodna metoda.


1
@androiddeveloper OnGlobal! = GlobalOn
marijnz0r 18.08.16

@ marijnz0r Jak dziwne. O co ci chodzi?
programista Androida

@androiddeveloper Nie wiem, ale zdarzyło mi się myśleć tak samo, jak kilka dni temu. Zobacz: stackoverflow.com/a/19216041/4587214
marijnz0r

@ marijnz0r Więc oboje robią to samo. Przypomina mi inne przypadki, że nadali nową nazwę już istniejącemu materiałowi, a poprzedni przestarzały. Przykład „fill_parent” vs „match_parent”: developer.android.com/reference/android/view/…
programista Androida

1

Ponieważ tryb wielu okien jest już dostępny, aplikacja może nie mieć paska stanu u góry.

Po rozwiązaniu automatycznie załatw wszystkie sprawy.

android:fitsSystemWindows="true"

lub programowo

findViewById(R.id.your_root_view).setFitsSystemWindows(true);

możesz również uzyskać widok roota przez

findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)

Aby uzyskać więcej informacji na temat uzyskiwania widoku głównego, patrz: https://stackoverflow.com/a/4488149/9640177


0

Ten problem stał się ostatnio dla mnie istotny ze względu na wycięcie w moim Pixelu 3XL. Naprawdę podobało mi się rozwiązanie dla programistów Androida , ale chciałem mieć możliwość uzyskania wysokości paska stanu do woli, ponieważ było to szczególnie potrzebne do animacji pełnoekranowej, w którą musiałem grać. Poniższa funkcja umożliwiła niezawodne zapytanie:

private val DEFAULT_INSET = 96
fun getInsets(view: View?): Int {
     var inset = DEFAULT_INSET
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Safe because only P supports notches
          inset = view?.rootWindowInsets?.stableInsetTop ?: DEFAULT_INSET
     }
     return inset
}

fun blurView(rootView: View?, a: SpacesActivity?) {
    val screenBitmap = getBitmapFromView(rootView!!)
    val heightDifference = getInsets(rootView)
    val croppedMap = Bitmap.createBitmap(
                    screenBitmap, 0, heightDifference,
                    screenBitmap.width,
                    screenBitmap.height - heightDifference)
    val blurredScreen = blurBitmap(croppedMap)
    if (blurredScreen != null) {
         val myDrawable = BitmapDrawable(a!!.resources, blurredScreen)
         a.errorHudFrameLayout?.background = myDrawable
         a.appBarLayout?.visibility = View.INVISIBLE
   }
}

A potem w klasie aktywności:

fun blurView() {
    this.runOnUiThread {
        Helper.blurView(this)
    }
}

Oczywiście będziesz chciał przekazać słabe odniesienie aktywności do parametru metody statycznej klasy Helper, ale dla zwięzłości powstrzymałem się w tym przykładzie. blurBitmapI errorHudFrameLayoutsą pomijane z tego samego powodu, ponieważ nie odnoszą się bezpośrednio do uzyskania wysokość paska stanu.


Jeśli dotyczy to systemu Android P i nowszego, po co sprawdzać w systemie Android M? Co byś zrobił, jeśli nie masz instancji View? Na przykład, jeśli nie masz obecnie Aktywności ...
programista Androida

M jest najwcześniejszym możliwym do sprawdzenia stableInsetTop i nawet jeśli tylko wycięcia obsługiwane przez P wolałbym uzyskać rzeczywistą wstawkę, zamiast wracać do wartości domyślnej, gdzie mogę. To rozwiązanie nie działa, jeśli nie masz aktywności.
James Jordan Taylor,

Widzę. Dziękuję Ci. Czy możesz podać bardziej „pełny” przykład?
programista Androida

Zmieniłem powyższą odpowiedź, aby użyć metody w przykładzie.
James Jordan Taylor

0

Wersja Kotlin, która łączy dwa najlepsze rozwiązania

fun getStatusBarHeight(): Int {
    val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
    return if (resourceId > 0) resources.getDimensionPixelSize(resourceId)
    else Rect().apply { window.decorView.getWindowVisibleDisplayFrame(this) }.top
}
  1. Trwa status_bar_height wartość, jeśli występuje
  2. Jeśli status_bar_heightnie jest obecny, oblicza wysokość paska stanu na podstawie wystroju okna
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.