Obsługa różnych rozmiarów ekranu

Obsługa różnych rozmiarów ekranu umożliwia dostęp do aplikacji na jak największej liczbie urządzeń i największej liczbie użytkowników.

Aby układy aplikacji były dostosowane do jak największej liczby rozmiarów ekranu, zaprojektuj je tak, aby były elastyczne i adaptacyjne. Układy elastyczne i adaptacyjne zapewniają wygodę użytkowników niezależnie od rozmiaru ekranu. Dzięki temu aplikacja może wyświetlać się na telefonach, tabletach, urządzeniach składanych i urządzeniach z ChromeOS oraz w orientacji pionowej i poziomej, a także konfigurować możliwość zmiany rozmiaru, np. tryb wielu okien.

Klasy rozmiaru okna

Klasy rozmiaru okna to zestaw sprawdzonych punktów przerwania widocznego obszaru, który pomaga w projektowaniu, tworzeniu i testowaniu układów elastycznych/adaptacyjnych. Punkty przerwania równoważą prosty układ z elastycznością, która pozwala zoptymalizować aplikację pod kątem unikalnych przypadków.

Klasy rozmiaru okna dzielą obszar wyświetlania dostępny w aplikacji na kompaktowy, średni lub rozwinięty. Dostępne szerokości i wysokości są klasyfikowane oddzielnie, więc w dowolnym momencie aplikacja ma 2 klasy rozmiaru okna – jedną dla szerokości i jedną dla wysokości. Dostępna szerokość jest zwykle ważniejsza niż dostępna wysokość ze względu na wszechobecność przewijania w pionie – klasa „width” (szerokość okna) prawdopodobnie lepiej pasuje do interfejsu aplikacji.

Rysunek 1. Klasy rozmiaru okna oparte na szerokości.
Rysunek 2. Klasy rozmiaru okna oparte na wysokości.

Jak widać na rysunkach, punkty przerwania pozwalają zastanawiać się nad układami w kontekście urządzeń i konfiguracji. Każdy punkt przerwania klasy rozmiaru reprezentuje większość przypadków w typowych scenariuszach urządzeń i może być wskazówką przy tworzeniu układów opartych na tych punktach.

Klasa rozmiaru Punkt przerwania Reprezentacja urządzenia
Kompaktowa szerokość szerokość < 600 dp 99,96% telefonów w orientacji pionowej
Średnia szerokość 600 dp ≤ szerokość < 840 dp 93,73% tabletów jest w orientacji pionowej.

najbardziej duże po rozłożeniu wewnętrzne wyświetlacze w orientacji pionowej

Szerokość po rozwinięciu szerokość ≥ 840 dp 97,22% tabletów w orientacji poziomej.

najbardziej duże po rozłożeniu wewnętrzne wyświetlacze w orientacji poziomej

Kompaktowa wysokość wysokość < 480 dp 99,78% telefonów wyświetla się w orientacji poziomej
Średni wzrost 480 dp ≤ wysokość < 900 dp 96,56% tabletów w orientacji poziomej.

97,59% telefonów w orientacji pionowej

Wysokość po rozwinięciu wysokość ≥ 900 dp 94,25% tabletów w orientacji pionowej

Chociaż wizualizowanie klas rozmiarów jako urządzeń fizycznych może być przydatne, klasy rozmiarów okien nie są wyraźnie określane przez rozmiar ekranu urządzenia. Klasy rozmiaru okna nie są przeznaczone dla logiki typu isTablet. Klasy rozmiaru okna są natomiast określane na podstawie rozmiaru okna dostępnego dla aplikacji niezależnie od typu urządzenia, na którym aplikacja działa, co ma 2 ważne konsekwencje:

  • Urządzenia fizyczne nie gwarantują określonej klasy rozmiaru okna. Przestrzeń dostępna na ekranie aplikacji może z wielu powodów różnić się od rozmiaru ekranu urządzenia. Na urządzeniach mobilnych tryb podzielonego ekranu może partycjonować ekran między 2 aplikacjami. W ChromeOS aplikacje na Androida mogą być wyświetlane w swobodnych oknach, których rozmiar można dowolnie zmieniać. Urządzenia składane mogą mieć 2 ekrany w różnych rozmiarach. Można je otworzyć po złożeniu lub rozłożeniu.

  • Klasa rozmiaru okna może zmieniać się przez cały czas używania aplikacji. Ilość dostępnego miejsca może zmieniać się przez cały czas używania aplikacji, dlatego zmiany orientacji urządzenia, wykonywanie wielu zadań jednocześnie oraz składanie i rozwijanie mogą mieć wpływ na ilość dostępnego miejsca. W efekcie klasa rozmiaru okna jest dynamiczna, a interfejs aplikacji powinien odpowiednio się dostosowywać.

Klasy rozmiaru okna mapują się na punkty przerwania układu w siatce układu elastycznego interfejsu Material Design. Używaj klas rozmiaru okna, aby podejmować ogólne decyzje dotyczące układu aplikacji, np. określać, czy użyć określonego układu kanonicznego, aby wykorzystać dodatkową przestrzeń na ekranie.

Możesz obliczyć bieżącą wartość WindowSizeClass, korzystając z funkcji WindowSizeClass#compute() dostępnej z biblioteki Jetpack WindowManager. Poniżej znajdziesz przykład obliczania klasy rozmiaru okna i otrzymywania aktualizacji po każdej zmianie klasy rozmiaru okna:

Kotlin

class MainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ...

        // 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)
                computeWindowSizeClasses()
            }
        })

        computeWindowSizeClasses()
    }

    private fun computeWindowSizeClasses() {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)
        val width = metrics.bounds.width()
        val height = metrics.bounds.height()
        val density = resources.displayMetrics.density
        val windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass
        // COMPACT, MEDIUM, or EXPANDED
        val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...

        // 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);
                computeWindowSizeClasses();
            }
        });

        computeWindowSizeClasses();
    }

    private void computeWindowSizeClasses() {
        WindowMetrics metrics = WindowMetricsCalculator.getOrCreate()
                .computeCurrentWindowMetrics(this);

        int width = metrics.getBounds().width
        int height = metrics.getBounds().height()
        float density = getResources().getDisplayMetrics().density;
        WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass()
        // COMPACT, MEDIUM, or EXPANDED
        WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass()

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Gdy zaczniesz obserwować w swojej aplikacji klasy rozmiaru okna, możesz zacząć zmieniać układ na podstawie bieżącej klasy rozmiaru okna.

Układy i klasy rozmiarów okien

Wprowadzając zmiany układu, przetestuj jego działanie we wszystkich rozmiarach okien, zwłaszcza przy małych, średnich i rozwiniętych szerokościach punktów przerwania.

Jeśli masz już układ dostosowany do kompaktowych ekranów, najpierw zoptymalizuj układ pod kątem klasy rozmiaru rozwiniętego, ponieważ ta klasa zapewnia najwięcej miejsca na dodatkowe treści i zmiany interfejsu. Następnie zdecyduj, jaki układ będzie odpowiedni dla klasy o średniej szerokości. Rozważ dodanie specjalistycznego układu.

Dalsze kroki

Więcej informacji o używaniu klas rozmiaru okna do tworzenia układów elastycznych i adaptacyjnych znajdziesz w tych artykułach:

Aby dowiedzieć się więcej o tym, co sprawia, że aplikacja jest tak popularna na wszystkich urządzeniach i na ekranach różnych urządzeń, zapoznaj się z tymi materiałami: