Używanie klas rozmiarów okien

Wypróbuj tworzenie wiadomości
Jetpack Compose to zalecany zestaw narzędzi interfejsu na Androida. Dowiedz się, jak korzystać z klas rozmiaru okna w Compose.

Klasy rozmiarów okna to zestaw punktów przecięcia widocznego obszaru, które pomagają projektować, tworzyć i testować elastyczne lub adaptacyjne układy. Punkty graniczne zapewniają równowagę między prostotą układu a elastycznością optymalizacji aplikacji pod kątem wyjątkowych przypadków.

Klasy rozmiarów okna dzielą obszar wyświetlania dostępny dla aplikacji na kompaktowy, średni, rozwinięty, duży lub bardzo duży. Dostępna szerokość i wysokość są klasyfikowane osobno, 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 powszechność przewijania w poziomie, dlatego klasa rozmiaru okna pod względem szerokości jest prawdopodobnie bardziej odpowiednia dla interfejsu aplikacji.

Rysunek 1. Reprezentacje klas rozmiarów okien na podstawie szerokości.
Rysunek 2. Reprezentacje klas rozmiarów okien na podstawie ich wysokości.

Jak widać na rysunkach, punkty graniczne pozwalają nadal myśleć o układzie w kategoriach urządzeń i konfiguracji. Każdy punkt odniesienia klasy rozmiaru odpowiada większości przypadków typowych scenariuszy urządzeń. Może to być przydatne podczas projektowania układów opartych na punktach odniesienia.

Klasa rozmiaru Punkt przerwania Reprezentacja urządzenia
Szerokość kompaktowa szerokość < 600 dp 99,96% telefonów w układzie pionowym
Średnia szerokość 600 dp ≤ szerokość < 840 dp 93,73% tabletów w układzie pionowym,

większość dużych rozłożonych wewnętrznych ekranów w orientacji pionowej

Szerokość po rozwinięciu 840 dp ≤ szerokość < 1200 dp 97,22% tabletów w orientacji poziomej,

większość dużych rozłożonych wewnętrznych ekranów w orientacji poziomej ma co najmniej: szerokość po rozłożeniu

Duża szerokość Szerokość: 1200 dp ≤ szerokość < 1600 dp Duże wyświetlacze tabletów
Szerokość bardzo duża szerokość ≥ 1600 dp Wyświetlacze biurkowe
Kompaktowa wysokość wysokość < 480 dp 99,78% telefonów w orientacji poziomej
Średnia wysokość 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

Wizualizacja klas rozmiarów jako urządzeń fizycznych może być przydatna, ale klasy rozmiarów okien nie są określane przez rozmiar ekranu urządzenia. Klasy rozmiaru okna nie są przeznaczone do logiki typu isTablet. Klasy rozmiarów okien są określane na podstawie rozmiaru okna dostępnego dla aplikacji niezależnie od typu urządzenia, na którym aplikacja działa. Ma to 2 ważne konsekwencje:

  • Urządzenia fizyczne nie gwarantują określonej klasy rozmiaru okna. Miejsce na ekranie dostępne dla aplikacji może się różnić od rozmiaru ekranu urządzenia z wielu powodów. Na urządzeniach mobilnych tryb podzielonego ekranu może podzielić ekran na 2 aplikacje. W ChromeOS aplikacje na Androida mogą być wyświetlane w oknach typu desktop, które można dowolnie zmieniać. Urządzenia składane mogą mieć 2 ekrany o różnych rozmiarach, do których można uzyskać dostęp, składając lub rozkładając urządzenie.

  • Klasa rozmiaru okna może się zmieniać w trakcie działania aplikacji.Podczas jej działania zmiana orientacji urządzenia, korzystanie z wielu aplikacji jednocześnie oraz składanie i rozkładanie mogą wpływać na ilość dostępnej przestrzeni na ekranie. W rezultacie klasa rozmiaru okna jest dynamiczna, a interfejs aplikacji powinien się odpowiednio dostosować.

Klasy rozmiarów okien odpowiadają punktom przerwania w układówce Material Design w wersji kompaktowej, średniej i rozwiniętej. Używaj klas rozmiarów okien, aby podejmować ogólne decyzje dotyczące układu aplikacji, na przykład decyduj, czy użyć konkretnego kanonicznego układu, aby wykorzystać dodatkową przestrzeń ekranu.

Możesz obliczyć bieżącą WindowSizeClass za pomocą WindowSizeClass#compute() funkcja dostępna w Jetpack WindowManager. Przykład poniżej pokazuje, jak obliczyć klasę rozmiaru okna i otrzymywać aktualizacje za każdym razem, zmiany 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.
    }
}

Testowanie klas rozmiarów okien

Po wprowadzeniu zmian w układzie sprawdź jego działanie w przypadku wszystkich rozmiarów okna, szczególnie w przypadku szerokości punktów przełamania w ustawieniach „Kompaktowy”, „Średni” i „Rozwinięty”.

Jeśli masz już układ dla ekranów kompaktowych, najpierw zoptymalizuj go pod kątem klasy rozmiaru z rozszerzoną szerokością, ponieważ ta klasa rozmiaru zapewnia najwięcej miejsca na dodatkowe treści i zmiany interfejsu. Następnie zdecyduj, jaki układ ma sens w przypadku klasy średniej szerokości; rozważ dodanie układu specjalistycznego.

Dalsze kroki

Więcej informacji o używaniu klas rozmiarów okien do tworzenia responsywnych/adaptacyjnych układów znajdziesz w tych artykułach:

Aby dowiedzieć się więcej o tym, co sprawia, że aplikacja działa świetnie na wszystkich urządzeniach i ekranach, zapoznaj się z tymi materiałami: