Aplikacja działa świetnie na telefonach w orientacji pionowej, więc ograniczyliśmy ją tylko do tej orientacji. Ale widzisz też możliwości, jakie dają duże ekrany w orientacji poziomej.
Jak można ograniczyć aplikację do orientacji pionowej na małych ekranach, a na dużych włączyć orientację poziomą?
Ten przewodnik jest rozwiązaniem tymczasowym, dopóki nie ulepszysz aplikacji, aby zapewniała pełną obsługę wszystkich konfiguracji urządzeń.
Zarządzanie orientacją aplikacji
Aby włączyć orientację poziomą na dużych ekranach, ustaw w pliku manifestu aplikacji domyślne obsługiwanie zmian orientacji. W czasie wykonywania określaj rozmiar okna aplikacji. Jeśli okno aplikacji jest małe, ogranicz orientację aplikacji, zastępując ustawienie orientacji w pliku manifestu.
1. Określanie ustawienia orientacji w manifeście aplikacji
Możesz nie deklarować elementu screenOrientation
w pliku manifestu aplikacji (w takim przypadku orientacja jest domyślnie ustawiana na unspecified
) lub ustawić orientację ekranu na fullUser
. Jeśli użytkownik nie zablokuje obracania na podstawie czujnika, aplikacja będzie obsługiwać wszystkie orientacje urządzenia.
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
Różnica między unspecified
a fullUser
jest subtelna, ale ważna. Jeśli nie określisz wartości screenOrientation
, system wybierze orientację, a zasada, której używa do jej zdefiniowania, może się różnić w zależności od urządzenia. Z drugiej strony, ustawienie fullUser
lepiej odpowiada zachowaniu zdefiniowanemu przez użytkownika na urządzeniu: jeśli użytkownik zablokował obracanie na podstawie czujnika, aplikacja będzie działać zgodnie z ustawieniami użytkownika. W przeciwnym razie system zezwoli na każdą z 4 możliwych orientacji ekranu (portret, pozioma, odwrócona orientacja pionowa lub odwrócona orientacja pozioma). Zobacz screenOrientation
.
2. Określanie rozmiaru ekranu
Jeśli manifest jest skonfigurowany tak, aby obsługiwać wszystkie orientacje dozwolone przez użytkownika, możesz określić orientację aplikacji programowo na podstawie rozmiaru ekranu.
Dodaj biblioteki Jetpack WindowManager do pliku build.gradle
lub build.gradle.kts
modułu:
Kotlin
implementation("androidx.window:window:version
") implementation("androidx.window:window-core:version
")
Groovy
implementation 'androidx.window:window:version
' implementation 'androidx.window:window-core:version
'
Użyj metody Jetpack WindowManager
WindowMetricsCalculator#computeMaximumWindowMetrics()
, aby uzyskać rozmiar ekranu urządzenia jako obiekt WindowMetrics
. Dane okna można porównać z klasami rozmiarów okna, aby określić, kiedy należy ograniczyć orientację.
Klasy rozmiarów okien wyznaczają punkty graniczne między małymi a dużymi ekranami.
Aby określić rozmiar ekranu, użyj punktów granicznych WindowWidthSizeClass#COMPACT
i WindowHeightSizeClass#COMPACT
:
Kotlin
/** Determines whether the device has a compact screen. **/ fun compactScreen() : Boolean { val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT }
Java
/** Determines whether the device has a compact screen. **/ private boolean compactScreen() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this); int width = metrics.getBounds().width(); int height = metrics.getBounds().height(); float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density); return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT || windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT; }
- Uwaga:
- Przykłady są implementowane jako metody aktywności, więc w argumencie
computeMaximumWindowMetrics()
odwołują się do niej jakothis
. - Metoda
computeMaximumWindowMetrics()
jest używana zamiast metodycomputeCurrentWindowMetrics()
, ponieważ aplikację można uruchomić w trybie wielu okien, który ignoruje ustawienie orientacji ekranu. Nie ma sensu określanie rozmiaru okna aplikacji i zastępowanie ustawienia orientacji, chyba że okno aplikacji zajmuje cały ekran urządzenia.
W klasie WindowManager znajdziesz instrukcje deklarowania zależności, aby udostępnić w aplikacji metodę computeMaximumWindowMetrics()
.
3. Zastępowanie ustawienia manifestu aplikacji
Gdy ustalisz, że urządzenie ma kompaktowy rozmiar ekranu, możesz wywołać Activity#setRequestedOrientation()
, aby zastąpić ustawienie screenOrientation
w pliku manifestu:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER } }) }
Java
@Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstanceState); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } } }); }
Dodając logikę do metod onCreate()
i View.onConfigurationChanged()
, możesz uzyskać dane o maksymalnej wielkości okna i przesłonić ustawienie orientacji, gdy rozmiar aktywności ulegnie zmianie lub gdy zostanie ona przeniesiona między wyświetlaczami, np. po obróceniu urządzenia lub po złożeniu i rozłożeniu urządzenia składanego.
Więcej informacji o tym, kiedy występują zmiany konfiguracji i kiedy powodują one odtworzenie aktywności, znajdziesz w artykule Zarządzanie zmianami konfiguracji.
Najważniejsze punkty
screenOrientation
: ustawienie w manifeście aplikacji, które umożliwia określenie sposobu reakcji aplikacji na zmiany orientacji urządzenia.- Jetpack WindowManager: zestaw bibliotek, które umożliwiają określenie rozmiaru i formatu obrazu okna aplikacji; zgodny z poprzednimi wersjami do poziomu interfejsu API 14.
Activity#setRequestedOrientation()
: metoda, za pomocą której możesz zmienić orientację aplikacji w czasie wykonywania
Wyniki
Aplikacja powinna teraz pozostać w orientacji pionowej na małych ekranach niezależnie od obracania urządzenia. Na dużych ekranach aplikacja powinna obsługiwać orientację poziomą i pionową.
Kolekcje zawierające ten przewodnik
Ten przewodnik jest częścią tych wyselekcjonowanych kolekcji krótkich przewodników, które obejmują szersze cele związane z tworzeniem aplikacji na Androida:
![](https://developer.android.com/static/images/quick-guides/collection-illustration.png?hl=pl)