Wyświetlaj zawartość w aplikacji od krawędzi do krawędzi

Wypróbuj sposób tworzenia wiadomości
Jetpack Compose to zalecany zestaw narzędzi UI na Androida. Dowiedz się, jak korzystać z wersji od brzegu do krawędzi w Compose

Gdy ustawisz kierowanie na pakiet SDK 35 lub nowszy na urządzeniu z Androidem 15 lub nowszym, Twoja aplikacja będzie wyświetlać się od krawędzi do krawędzi. Okno rozciąga się za całą szerokość i wysokość wyświetlacza, rysując za słupkami systemowymi. Paski systemowe obejmują pasek stanu, napisy i pasek nawigacyjny.

Wiele aplikacji ma górny pasek aplikacji. Górny pasek aplikacji powinien rozciągać się do górnej krawędzi ekranu i wyświetlać za paskiem stanu. Opcjonalnie podczas przewijania treści górny pasek aplikacji może się zmniejszać do wysokości paska stanu.

Wiele aplikacji ma też dolny pasek aplikacji lub dolny pasek nawigacyjny. Paski powinny się rozciągać do dolnej krawędzi ekranu i wyświetlać się za paskiem nawigacyjnym. W przeciwnym razie aplikacje powinny pokazywać przewijaną treść za paskiem nawigacyjnym.

Rysunek 1. Paski systemowe w układzie od krawędzi do krawędzi.

Implementując układ od brzegu do krawędzi w aplikacji, pamiętaj o tych kwestiach:

  1. Włączanie wyświetlania od krawędzi do krawędzi
  2. Rozwiązuj problemy z wizualnymi nakładającymi się treściami.
  3. Rozważ wyświetlanie ram za pasami systemowymi.
przykładowy obraz za paskiem stanu
Rysunek 2. Przykład zdjęć za paskiem stanu.

Włącz wyświetlanie od krawędzi do krawędzi

Jeśli Twoja aplikacja jest kierowana na pakiet SDK 35 lub nowszy, na urządzeniach z Androidem 15 i nowszym proces brzegowy jest automatycznie włączony.

Aby włączyć połączenia brzegowe w poprzednich wersjach Androida, wykonaj te czynności:

  1. Dodaj zależność do biblioteki androidx.activity w pliku build.gradle aplikacji lub modułu:

    Kotlin

    dependencies {
        val activity_version = activity_version
        // Java language implementation
        implementation("androidx.activity:activity:$activity_version")
        // Kotlin
        implementation("androidx.activity:activity-ktx:$activity_version")
    }
    

    Odlotowe

    dependencies {
        def activity_version = activity_version
        // Java language implementation
        implementation 'androidx.activity:activity:$activity_version'
        // Kotlin
        implementation 'androidx.activity:activity-ktx:$activity_version'
    }
    
  2. Zaimportuj funkcję rozszerzenia enableEdgeToEdge do aplikacji:

Ręcznie włącz połączenia od brzegu do brzegu, wywołując metodę enableEdgeToEdge w onCreate z Activity. Powinna zostać wywołana przed setContentView.

Kotlin

     override fun onCreate(savedInstanceState: Bundle?) {
       enableEdgeToEdge()
       super.onCreate(savedInstanceState)
       ...
     }
   

Java

     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
       EdgeToEdge.enable(this);
       super.onCreate(savedInstanceState);
       ...
     }
   

Domyślnie enableEdgeToEdge() ukrywa paski systemowe. Wyjątkiem jest tryb nawigacji przy użyciu 3 przycisków, w którym pasek stanu wyświetla się przezroczystą ramkę. Kolory ikon systemowych i ekranu są dostosowywane w zależności od jasnego lub ciemnego motywu systemu.

Funkcja enableEdgeToEdge() automatycznie deklaruje, że aplikacja powinna być nałożona od krawędzi do krawędzi, i dostosowuje kolory pasków systemowych.

Informacje o tym, jak włączyć wyświetlanie od krawędzi do krawędzi w aplikacji bez używania funkcji enableEdgeToEdge(), znajdziesz w artykule Ręczne konfigurowanie wyświetlacza od krawędzi do krawędzi.

Obsługa nakładających się elementów za pomocą wkładek

Niektóre widoki aplikacji mogą być widoczne za paskami systemowymi, jak widać na rysunku 3.

Możesz rozwiązać problem z nakładaniem się, reagując na wcięcia określające, które części ekranu przecinają się z interfejsem systemowym, takim jak pasek nawigacyjny lub pasek stanu. Krzyżowanie może oznaczać wyświetlanie nad treścią, ale może też informować aplikację o gestach systemowych.

Typy wstawienia reklamy, które mają zastosowanie do wyświetlania aplikacji od krawędzi do krawędzi:

  • Wstawki systemowe w postaci słupków: najlepiej sprawdzają się w przypadku widoków, które można kliknąć i które nie mogą być zasłonięte słupkami systemowymi.

  • Wcięcia w wycięciach w ekranie: w obszarach, w których ze względu na kształt urządzenia może pojawić się wycięcie w ekranie.

  • Wstawki za pomocą gestów: dotyczą obszarów nawigacji przy użyciu gestów, które są używane przez system, które mają wyższy priorytet niż aplikacja.

Wcięcia słupków systemowych

Najczęściej stosowanym typem wkładek są systemowe wstawki. Reprezentują obszar, w którym interfejs systemu wyświetla się na osi Z nad aplikacją. Służą one do przesuwania lub uzupełniania widoków w aplikacji, które można kliknąć. Nie mogą też być zasłonięte słupkami systemu.

Na przykład pływający przycisk polecenia na ilustracji 3 jest częściowo zasłonięty paskiem nawigacyjnym:

przykład implementacji od krawędzi do krawędzi, ale pasek nawigacyjny zakrywa przycisk PPP
Rysunek 3. Pasek nawigacyjny zachodzący na przycisk PPP w układzie od krawędzi do krawędzi.

Aby uniknąć tego rodzaju nakładania się elementów w trybie gestu lub przycisku, możesz zwiększyć marginesy widoku za pomocą funkcji getInsets(int) i WindowInsetsCompat.Type.systemBars().

Poniższy przykładowy kod pokazuje, jak wdrożyć systemowe wstawki słupkowe:

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets ->
  val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
  // Apply the insets as a margin to the view. This solution sets
  // only the bottom, left, and right dimensions, but you can apply whichever
  // insets are appropriate to your layout. You can also update the view padding
  // if that's more appropriate.
  v.updateLayoutParams<MarginLayoutParams> {
      leftMargin = insets.left,
      bottomMargin = insets.bottom,
      rightMargin = insets.right,
  }

  // Return CONSUMED if you don't want want the window insets to keep passing
  // down to descendant views.
  WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> {
  Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
  // Apply the insets as a margin to the view. This solution sets only the
  // bottom, left, and right dimensions, but you can apply whichever insets are
  // appropriate to your layout. You can also update the view padding if that's
  // more appropriate.
  MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
  mlp.leftMargin = insets.left;
  mlp.bottomMargin = insets.bottom;
  mlp.rightMargin = insets.right;
  v.setLayoutParams(mlp);

  // Return CONSUMED if you don't want want the window insets to keep passing
  // down to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

Jeśli zastosujesz to rozwiązanie do przykładu pokazanego na ilustracji 3, w trybie przycisku nie będzie nakładać się, jak widać na rysunku 4:

półprzezroczysty pasek nawigacyjny bez przycisku PPP.
Rysunek 4. Rozwiązywanie problemów z nakładaniem się elementów wizualnych w trybie przycisku.

To samo dotyczy trybu nawigacji przy użyciu gestów, jak widać na rysunku 5:

od krawędzi do krawędzi dzięki nawigowaniu przy użyciu gestów
Rysunek 5. Rozwiązywanie problemu z nakładaniem się elementów wizualnych w trybie nawigacji przy użyciu gestów.

Zestawy do wycięcia w ekranie

Niektóre urządzenia mają wycięcia w ekranie. Wycięcie zazwyczaj znajduje się u góry ekranu i znajduje się na pasku stanu. Gdy ekran urządzenia jest w trybie poziomym, wycięcie może znajdować się na pionowej krawędzi. W zależności od tego, jakie treści aplikacja wyświetla na ekranie, należy zastosować dopełnienie, aby uniknąć wycięć w ekranie. Domyślnie aplikacje rysują w wycięciu w ekranie.

Na przykład na wielu ekranach aplikacji wyświetla się lista elementów. Nie zasłaniaj elementów listy wycięciem w ekranie ani paskami systemowymi.

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets ->
  val bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
      or WindowInsetsCompat.Type.displayCutout()
  )
  v.updatePadding(
    left = bars.left,
    top = bars.top,
    right = bars.right,
    bottom = bars.bottom,
  )
  WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> {
  WindowInsetsCompat bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
    | WindowInsetsCompat.Type.displayCutout()
  );
  v.setPadding(bars.left, bars.top, bars.right, bars.bottom);
  return WindowInsetsCompat.CONSUMED;
});

Określ wartość WindowInsetsCompat, stosując operator logiczny lub słupków systemowych i typów wycięcia w ekranie.

Ustaw clipToPadding na RecyclerView, aby dopełnienie przewijało się razem z elementami listy. Dzięki temu elementy mogą pojawiać się za paskami systemowymi, gdy użytkownik przewija stronę, jak pokazano w przykładzie poniżej.

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

Systemowe wstawki gesty

Gesty systemowe to obszary okna, w których gesty systemowe mają wyższy priorytet niż Twoja aplikacja. Na ilustracji 6 te obszary są zaznaczone na pomarańczowo:

Przykład systemowego wstawienia gestów
Rysunek 6. Systemowe wstawki gesty.

Podobnie jak w przypadku wkładek słupków systemowych możesz uniknąć nakładania się wstawienia gestów systemu za pomocą właściwości getInsets(int) i WindowInsetsCompat.Type.systemGestures().

Te wstawki umożliwiają odsunięcie widoków przesuwanych od krawędzi lub odsunięcie ich od krawędzi. Typowe przypadki użycia to dolne arkusze, przesuwanie w grach i karuzele zaimplementowane za pomocą ViewPager2.

W Androidzie 10 i nowszych wstawki systemowe zawierają dolną wkładkę dla gestu Home oraz wstążkę lewą i prawą dla gestów cofania.

przykład pomiarów wstawionych gestami systemowymi
Rysunek 7. Pomiary wstawiane za pomocą gestów.

Ten przykładowy kod pokazuje, jak wdrożyć systemowe wstawki gesty:

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
    val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
    Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures());
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.setPadding(insets.left, insets.top, insets.right, insets.bottom);

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

Tryb imersji

Niektóre treści najlepiej oglądać na pełnym ekranie, ponieważ są one bardziej wciągające. Aby ukryć paski systemowe w trybie pojemnym, użyj bibliotek WindowInsetsController i WindowInsetsControllerCompat:

Kotlin

val windowInsetsController =
      WindowCompat.getInsetsController(window, window.decorView)

// Hide the system bars.
windowInsetsController.hide(Type.systemBars())

// Show the system bars.
windowInsetsController.show(Type.systemBars())

Java

Window window = getWindow();
WindowInsetsControllerCompat windowInsetsController =
      WindowCompat.getInsetsController(window, window.getDecorView());
if (windowInsetsController == null) {
    return;
  }
// Hide the system bars.
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars());

// Show the system bars.
windowInsetsController.show(WindowInsetsCompat.Type.systemBars());

Więcej informacji o implementowaniu tej funkcji znajdziesz w artykule Ukrywanie pasków systemowych w trybie pojemnym.

Dodatkowe materiały

W tym artykule znajdziesz więcej informacji o funkcji WindowInsets, nawigowaniu przy użyciu gestów i sposobie działania wstawienia: