Ograniczenie orientacji aplikacji na telefonach, ale nie na dużych ekranach

Ikona oceny dwóch gwiazdek

Twoja aplikacja świetnie działa na telefonach w orientacji pionowej, dlatego ograniczasz ją tylko do tej orientacji. Widzisz jednak możliwość zrobienia więcej na dużych ekranach w orientacji poziomej.

Jak możesz pogodzić te 2 kwestie – ograniczyć aplikację do orientacji pionowej na małych ekranach, ale włączyć orientację poziomą na dużych?

Sprawdzone metody

Najlepsze aplikacje uwzględniają preferencje użytkownika, takie jak orientacja urządzenia.

Wytyczne dotyczące jakości aplikacji adaptacyjnych zalecają, aby aplikacje obsługiwały wszystkie konfiguracje urządzeń, w tym orientację pionową i poziomą, tryb wielu okien oraz stan złożony i rozłożony urządzeń składanych. Aplikacje powinny optymalizować układy i interfejsy użytkownika pod kątem różnych konfiguracji oraz zapisywać i przywracać stan podczas zmian konfiguracji.

Ten przepis to rozwiązanie tymczasowe – odrobina obsługi dużych ekranów. Korzystaj z niego, dopóki nie uda Ci się ulepszyć aplikacji, aby w pełni obsługiwała wszystkie konfiguracje urządzeń.

Składniki

  • screenOrientation: ustawienie w pliku manifestu aplikacji, które umożliwia określenie, jak aplikacja reaguje na zmiany orientacji urządzenia.
  • Activity#setRequestedOrientation(): metoda, za pomocą której możesz zmienić orientację aplikacji w czasie działania.
  • LocalConfiguration: lokalny dostawca z możliwością komponowania, który udostępnia bieżące urządzenie Configuration, co pozwala odczytywać wymiary ekranu w dp.
  • LaunchedEffect: interfejs API efektu ubocznego Compose, który uruchamia blok kodu, gdy zmieni się klucz (w tym przypadku, gdy zmieni się konfiguracja).

Kroki

Włącz domyślnie obsługę zmian orientacji w pliku manifestu aplikacji. Następnie w czasie działania użyj Jetpack Compose, aby dynamicznie ograniczyć orientację do pionowej na kompaktowych ekranach (telefonach), a jednocześnie zezwolić na wszystkie orientacje na dużych ekranach.

1. Określ ustawienie orientacji w pliku manifestu aplikacji

Możesz uniknąć deklarowania elementu screenOrientation w pliku manifestu aplikacji (w takim przypadku orientacja domyślnie będzie ustawiona na unspecified) lub ustawić orientację ekranu na fullUser. Jeśli użytkownik nie zablokował obrotu opartego na czujniku, Twoja aplikacja będzie obsługiwać wszystkie orientacje urządzenia.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

Różnica między użyciem unspecified a fullUser jest subtelna, ale ważna. Jeśli nie zadeklarujesz wartości screenOrientation, system wybierze orientację, a zasady, których używa do jej określenia, mogą się różnić w zależności od urządzenia. Z drugiej strony, określenie fullUser lepiej odpowiada zachowaniu zdefiniowanemu przez użytkownika na urządzeniu: jeśli użytkownik zablokował obrót oparty na czujniku, aplikacja będzie się kierować jego preferencjami; w przeciwnym razie system zezwoli na dowolną z 4 możliwych orientacji ekranu (pionową, poziomą, pionową odwróconą lub poziomą odwróconą). Zobacz android:screenOrientation.

2. Dynamiczne ograniczanie orientacji w Compose

W Jetpack Compose możesz odczytywać bieżące wymiary ekranu w dp w sposób reaktywny z LocalConfiguration.current i używać LaunchedEffect, aby aktualizować orientację aktywności za każdym razem, gdy zmieni się konfiguracja.

Jeśli szerokość lub wysokość ekranu jest mniejsza niż 600dp (co odpowiada kompaktowemu punktowi przerwania dla telefonów), ogranicz orientację do pionowej. W przeciwnym razie pozwól systemowi obracać aplikację na podstawie preferencji użytkownika (unspecified lub fullUser).

Oto kompletna implementacja, którą można skompilować:

val configuration = LocalConfiguration.current
val context = LocalActivity.current

LaunchedEffect(configuration) {
    val activity = context ?: return@LaunchedEffect
    // Determine if screen is compact (phone-sized) in either width or height
    val isCompact = configuration.screenWidthDp < 600 || configuration.screenHeightDp < 600
    activity.requestedOrientation = if (isCompact) {
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    } else {
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    }
}

Dodając logikę w bloku LaunchedEffect(configuration), możesz reaktywnie zastępować ustawienie orientacji za każdym razem, gdy zmieni się konfiguracja aplikacji, np. gdy aktywność zostanie zmieniona, przeniesiona między wyświetlaczami lub gdy urządzenie składane zostanie złożone lub rozłożone.

Więcej informacji o tym, kiedy występują zmiany konfiguracji i kiedy powodują one ponowne utworzenie aktywności, znajdziesz w artykule Obsługa zmian konfiguracji.

Wyniki

Twoja aplikacja powinna teraz pozostawać w orientacji pionowej na małych ekranach niezależnie od obrotu urządzenia. Na dużych ekranach aplikacja powinna obsługiwać orientację poziomą i pionową.

Dodatkowe materiały

Aby uzyskać pomoc w uaktualnieniu aplikacji, tak aby zawsze obsługiwała wszystkie konfiguracje urządzeń, zapoznaj się z tymi materiałami: