Farklı ekran boyutlarının desteklenmesi, uygulamanıza en çeşitli cihazlardan ve en fazla sayıda kullanıcı tarafından erişilmesini sağlar.
Farklı cihaz ekranları veya çoklu pencere modundaki farklı uygulama pencereleri gibi mümkün olduğunca çok ekran boyutunu desteklemek için uygulama düzenlerinizi duyarlı ve uyarlanabilir olacak şekilde tasarlayın. Duyarlı/uyarlanabilir düzenler, ekran boyutundan bağımsız olarak optimize edilmiş bir kullanıcı deneyimi sunar. Böylece uygulamanız telefonlara, tabletlere, katlanabilir cihazlara, ChromeOS cihazlara, dikey ve yatay yönlere, bölünmüş ekran modu ve pencereli görüntüleme gibi yeniden boyutlandırılabilir ekran yapılandırmalarına uyum sağlayabilir.
Duyarlı/uyarlanabilir düzenler, mevcut görüntüleme alanına göre değişir. Değişiklikler, boşluğu dolduran küçük düzen ayarlamalarından (duyarlı tasarım) bir düzeni tamamen başka bir düzenle değiştirerek uygulamanızın farklı ekran boyutlarına en iyi şekilde uyum sağlamasına (uyarlanabilir tasarım) kadar çeşitlilik gösterir.
Bildirim temelli bir kullanıcı arayüzü araç seti olan Jetpack Compose, farklı ekran boyutlarında içeriği farklı şekilde oluşturmak için dinamik olarak değişen düzenler tasarlamak ve uygulamak için idealdir.
Android becerileri
GitHub'da gösterUygulamanızı uyarlanabilir hale getirme
adaptive Android becerisini kullanın.android skills add adaptiveİçerik düzeyindeki composable'lar için büyük düzen değişikliklerini açıkça belirtme
Uygulama düzeyinde ve içerik düzeyinde composable'lar, uygulamanızın kullanabileceği tüm görüntüleme alanını kaplar. Bu tür composable'lar için uygulamanızın büyük ekranlardaki genel düzenini değiştirmek mantıklı olabilir.
Düzen kararları verirken fiziksel donanım değerlerini kullanmaktan kaçının. Sabit ve somut bir değere (Cihaz tablet mi? Fiziksel ekranın belirli bir en boy oranı var mı?) ancak bu soruların yanıtları, kullanıcı arayüzünüz için kullanılabilir alanı belirlemede yararlı olmayabilir.
Tabletlerde uygulamalar çoklu pencere modunda çalışabilir. Bu durumda uygulama, ekranı başka bir uygulamayla paylaşabilir. Pencereli görüntüleme modunda veya ChromeOS'te uygulamalar yeniden boyutlandırılabilir bir pencerede olabilir. Katlanabilir cihazlarda olduğu gibi birden fazla fiziksel ekran da olabilir. Tüm bu durumlarda, içeriğin nasıl gösterileceğine karar vermek için fiziksel ekran boyutu önemli değildir.
Bunun yerine, Jetpack WindowManager kitaplığı tarafından sağlanan mevcut pencere metriklerinde açıklanan, uygulamanıza ayrılan ekranın gerçek bölümüne göre karar verin. WindowManager'ın bir Compose uygulamasında nasıl kullanılacağına dair örnek için JetNews örneğine bakın.
Düzenlerinizi kullanılabilir ekran alanına uyarlanabilir hale getirmek, ChromeOS gibi platformları ve tabletler ile katlanabilir cihazlar gibi form faktörlerini desteklemek için gereken özel işlem miktarını da azaltır.
Uygulamanız için kullanılabilir alanın metriklerini belirledikten sonra, ham boyutu Pencere boyutu sınıflarını kullanma bölümünde açıklandığı gibi bir pencere boyutu sınıfına dönüştürün. Pencere boyutu sınıfları, uygulama mantığının basitliği ile uygulamanızı çoğu ekran boyutuna göre optimize etme esnekliği arasında denge kurmak için tasarlanmış kesme noktalarıdır.
Pencere boyutu sınıfları, uygulamanızın genel penceresini ifade eder. Bu nedenle, uygulamanızın genel düzenini etkileyen düzen kararları için sınıfları kullanın. Pencere boyutu sınıflarını durum olarak iletebilir veya iç içe yerleştirilmiş composable'lara iletilecek türetilmiş durum oluşturmak için ek mantık uygulayabilirsiniz.
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true).windowSizeClass ) { // Decide whether to show the top app bar based on window size class. val showTopAppBar = windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) // MyScreen logic is based on the showTopAppBar boolean flag. MyScreen( showTopAppBar = showTopAppBar, /* ... */ ) }
Katmanlı yaklaşım, görüntü boyutu mantığını uygulamanızın senkronize edilmesi gereken birçok yerine dağıtmak yerine tek bir konumla sınırlandırır. Tek bir konum, diğer uygulama durumları gibi diğer composable'lara açıkça aktarılabilen bir durum üretir. Durumu açıkça iletmek, composable'lar pencere boyutu sınıfını veya belirtilen yapılandırmayı diğer verilerle birlikte aldığından bağımsız composable'ları basitleştirir.
Esnek iç içe yerleştirilmiş composable'lar yeniden kullanılabilir
Birleştirilebilir öğeler, çok çeşitli yerlere yerleştirilebildiğinde daha fazla yeniden kullanılabilir. Bir composable'ın belirli bir boyutta belirli bir konuma yerleştirilmesi gerekiyorsa composable'ın diğer bağlamlarda yeniden kullanılması pek mümkün değildir. Bu durum, yeniden kullanılabilir bağımsız composable'ların global ekran boyutu bilgilerine dolaylı olarak bağlı olmaması gerektiği anlamına da gelir.
Tek bir bölme veya yan yana iki bölme gösterebilen bir liste-ayrıntı düzeni uygulayan iç içe yerleştirilmiş bir composable düşünün:
Liste-ayrıntı düzeni kararı, uygulamanın genel düzeninin bir parçası olmalıdır. Bu nedenle karar, içerik düzeyinde bir composable'dan aktarılır:
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
Peki ya bir composable'ın düzenini, kullanılabilir görüntüleme alanına göre bağımsız olarak değiştirmesini istiyorsanız? Örneğin, alan izin veriyorsa ek ayrıntılar gösteren bir kart. Mevcut ekran boyutuna göre bir mantık uygulamak istiyorsunuz ancak tam olarak hangi boyuta göre?
Cihazın gerçek ekran boyutunu kullanmaya çalışmaktan kaçının. Bu, farklı ekran türleri için doğru olmayacağı gibi uygulama tam ekran değilse de doğru olmaz.
Oluşturulabilir öğe, içerik düzeyinde bir oluşturulabilir öğe olmadığından mevcut pencere metriklerini doğrudan kullanmayın.
Bileşen, dolguyla (ör. eklerle) yerleştirilirse veya uygulamada gezinme çubukları ya da uygulama çubukları gibi bileşenler varsa composable'ın kullanabileceği görüntüleme alanı, uygulamanın kullanabileceği toplam alandan önemli ölçüde farklı olabilir.
Composable öğenin kendisini oluşturmak için gerçekte verilen genişliği kullanın. Bu genişliği elde etmek için iki seçeneğiniz vardır:
İçeriğin nerede veya nasıl gösterileceğini değiştirmek istiyorsanız düzeni duyarlı hale getirmek için bir değiştirici koleksiyonu veya özel düzen kullanın. Bu, bir alt öğenin mevcut alanın tamamını doldurması kadar basit olabilir veya yeterli alan varsa alt öğeleri birden fazla sütunla düzenleyebilirsiniz.
Neyi gösterdiğinizi değiştirmek istiyorsanız daha güçlü bir alternatif olarak
BoxWithConstraintskullanın.BoxWithConstraints, kullanılabilir görüntüleme alanına göre farklı composable'ları çağırmak için kullanabileceğiniz ölçüm kısıtlamaları sağlar. Ancak bu durumun bazı dezavantajları vardır.BoxWithConstraints, oluşturma işlemini bu kısıtlamaların bilindiği düzen aşamasına kadar erteler. Bu da düzen aşamasında daha fazla işlem yapılmasına neden olur.
@Composable fun Card(/* ... */) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(/* ... */) Title(/* ... */) } } else { Row { Column { Title(/* ... */) Description(/* ... */) } Image(/* ... */) } } } }
Tüm verileri farklı ekran boyutlarında kullanılabilir hale getirme
Ek ekran alanından yararlanan bir composable uygularken verimli olmak ve verileri mevcut ekran boyutunun yan etkisi olarak yüklemek isteyebilirsiniz.
Ancak bu, tek yönlü veri akışı ilkesine aykırıdır. Bu ilkeye göre veriler, uygun şekilde oluşturulmak üzere kaldırılabilir ve composable'lara sağlanabilir. Oluşturulabilir öğeye, içeriğin bir kısmı her zaman kullanılmasa bile her ekran boyutu için her zaman yeterli içeriğe sahip olacak kadar veri sağlanmalıdır.
@Composable fun Card( imageUrl: String, title: String, description: String ) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description(description) } Image(imageUrl) } } } }
Card örneğini temel alarak, description değerinin her zaman Card değerine iletildiğini unutmayın. description yalnızca genişlik gösterilmesine izin verdiğinde kullanılsa da Card, kullanılabilir genişlikten bağımsız olarak her zaman description gerektirir.
Her zaman yeterli içerik iletmek, uyarlanabilir düzenleri daha az durum bilgili hale getirerek basitleştirir ve ekran boyutları arasında geçiş yaparken (pencere boyutunun yeniden boyutlandırılması, yön değişikliği veya cihazın katlanıp açılması nedeniyle gerçekleşebilir) yan etkilerin tetiklenmesini önler.
Bu ilke, düzen değişiklikleri sırasında durumun korunmasını da sağlar. Tüm ekran boyutlarında kullanılmayabilecek bilgileri yukarı taşıyarak düzen boyutu değiştiğinde uygulama durumunu koruyabilirsiniz.
Örneğin, ekranın yeniden boyutlandırılması düzenin içeriği gizleme ve gösterme arasında geçiş yapmasına neden olduğunda uygulama durumunun korunması için bir showMore boole işaretini yükseltebilirsiniz:
@Composable fun Card( imageUrl: String, title: String, description: String ) { var showMore by remember { mutableStateOf(false) } BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description( description = description, showMore = showMore, onShowMoreToggled = { newValue -> showMore = newValue } ) } Image(imageUrl) } } } }
Daha fazla bilgi
Compose'da uyarlanabilir düzenler hakkında daha fazla bilgi edinmek için aşağıdaki kaynaklara göz atın:
Örnek uygulamalar
- CanonicalLayouts, büyük ekranlarda optimum kullanıcı deneyimi sağlayan, kanıtlanmış tasarım kalıplarının bulunduğu bir depodur.
- JetNews, kullanıcı arayüzünü mevcut ekran alanını kullanacak şekilde uyarlayan bir uygulamanın nasıl tasarlanacağını gösterir.
- Reply; mobil cihazları, tabletleri ve katlanabilir cihazları destekleyen uyarlanabilir bir örnektir.
- Now in Android, farklı ekran boyutlarını desteklemek için uyarlanabilir düzenler kullanan bir uygulamadır.
Videolar
- Her ekran boyutuna uygun Android kullanıcı arayüzleri oluşturma
- Form Faktörleri | Android Dev Summit '22