Farklı ekran boyutları için destek, uygulamanıza en çeşitli cihazlardan ve en fazla sayıda kullanıcı tarafından erişilmesini sağlar.
Farklı cihaz ekranları veya çok pencereli moddaki farklı uygulama pencereleri gibi mümkün olduğunca çok sayıda 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. Bu sayede uygulamanız telefonları, tabletleri, katlanabilir cihazları, ChromeOS cihazları, dikey ve yatay yönlendirmeleri ve bölünmüş ekran modu ile masaüstü pencereli görüntüleme gibi yeniden boyutlandırılabilir ekran yapılandırmalarını destekleyebilir.
Duyarlı/uyarlanabilir düzenler, mevcut ekran alanına göre değişir. Değişiklikler, alanı dolduran küçük düzen ayarlamalarından (duyarlı tasarım) uygulamanızın farklı ekran boyutlarına en iyi şekilde uyum sağlaması için bir düzenin tamamen başka bir düzenle değiştirilmesine (uyarlanabilir tasarım) kadar çeşitlilik gösterir.
Bildirime dayalı bir kullanıcı arayüzü araç seti olan Jetpack Compose, içerikleri farklı ekran boyutlarında farklı şekilde oluşturmak için dinamik olarak değişen düzenler tasarlayıp uygulamak için idealdir.
İçerik düzeyindeki composable'lar için büyük düzen değişikliklerini açık hale getirme
Uygulama düzeyinde ve içerik düzeyinde composable'lar, uygulamanızın kullanabileceği tüm ekran alanını kaplar. Bu tür composable'lar için uygulamanızın genel düzenini büyük ekranlarda değiştirmek mantıklı olabilir.
Düzen kararları verirken fiziksel donanım değerlerini kullanmaktan kaçının. Kararları sabit bir somut değere göre vermek cazip gelebilir (Cihaz tablet mi? Fiziksel ekranın belirli bir en-boy oranı var mı? gibi sorular sorulabilir ancak bu soruların yanıtları, kullanıcı arayüzünüz için kullanılabilir alanı belirlemek açısından faydalı olmayabilir.
Tabletlerde bir uygulama, çok pencereli modda çalışıyor olabilir. Bu durumda uygulama, ekranı başka bir uygulamayla bölüyor olabilir. Masaüstü pencere modunda veya ChromeOS'te ise uygulama, yeniden boyutlandırılabilir bir pencerede olabilir. Katlanabilir cihazlarda olduğu gibi birden fazla fiziksel ekran da olabilir. Bu durumlarda, içeriğin nasıl görüntüleneceğine karar verirken fiziksel ekran boyutu önemli değildir.
Bunun yerine, Jetpack WindowManager kitaplığı tarafından sağlanan mevcut pencere metrikleriyle açıklanan, uygulamanıza ayrılan ekranın gerçek bölümüne göre kararlar alın. WindowManager'ı Compose uygulamasında kullanma örneği için JetNews örneğine bakın.
Düzenlerinizi mevcut 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 Pencere boyutu sınıflarını kullanma bölümünde açıklandığı gibi ham boyutu pencere boyutu sınıfına dönüştürün. Pencere boyutu sınıfları, uygulama mantığının basitliğini çoğu ekran boyutuna göre uygulamanızı optimize etme esnekliğiyle dengelemek için tasarlanmış kesme noktalarıdır.
Pencere boyutu sınıfları, uygulamanızın genel penceresini ifade eder. Bu nedenle, genel uygulama düzeninizi 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().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üleme boyutu mantığını uygulamanızın birçok yerine dağıtmak yerine tek bir konumla sınırlar. Bu sayede, senkronize edilmesi gereken birçok yer ortadan kalkar. Tek bir konum, diğer tüm uygulama durumları gibi diğer composable'lara açıkça aktarılabilen bir durum üretir. Durumun açıkça iletilmesi, composable'lar pencere boyutu sınıfını veya belirtilen yapılandırmayı diğer verilerle birlikte kullandığından tek tek composable'ları basitleştirir.
Esnek iç içe yerleştirilmiş composable'lar yeniden kullanılabilir
Composable'lar çok çeşitli yerlere yerleştirilebildiğinde daha fazla yeniden kullanılabilir. Bir composable'ın belirli bir boyutta belirli bir yere yerleştirilmesi gerekiyorsa bu composable'ın diğer bağlamlarda yeniden kullanılması olası değildir. Bu, tek tek kullanılabilen composable'ların global ekran boyutu bilgilerine örtülü 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 işlevi düşünün:
Liste-ayrıntı 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, bunun yerine, kullanılabilir görüntüleme alanına göre düzenini bağımsız olarak değiştirebilen bir composable istiyorsanız (ör. alan izin veriyorsa ek ayrıntılar gösteren bir kart) ne yapmalısınız? Kullanılabilir bazı görüntüleme boyutlarına göre belirli bir mantık uygulamak istiyorsunuz ancak hangi boyutu kullanacağınızdan emin değilsiniz.
Cihazın gerçek ekranının boyutunu kullanmaya çalışmayın. Bu değer, farklı ekran türleri için doğru olmayabilir ve uygulama tam ekran değilse de doğru olmayabilir.
Composable, içerik düzeyinde bir composable olmadığından mevcut pencere metriklerini doğrudan kullanmayın.
Bileşen dolguyla (ör. iç kısımlarla) yerleştirilmişse veya uygulamada gezinme çubukları ya da uygulama çubukları gibi bileşenler varsa composable'ın kullanabileceği görüntüleme alanı miktarı, uygulamanın kullanabileceği genel alandan önemli ölçüde farklı olabilir.
Composable'ın kendisini oluşturmak için gerçekten 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örüntülendiğini değiştirmek istiyorsanız düzeni duyarlı hale getirmek için bir değiştirici koleksiyonu ya da özel düzen kullanın. Bu, çocuğun mevcut alanın tamamını doldurması veya yeterli alan varsa çocukları birden fazla sütun halinde yerleştirmek kadar basit olabilir.
Gösterdiğiniz öğeleri değiştirmek istiyorsanız daha güçlü bir alternatif olarak
BoxWithConstraintssimgesini kullanın.BoxWithConstraints, ölçüm kısıtlamaları sağlar. Bu kısıtlamaları, kullanılabilir görüntüleme alanına göre farklı composable'ları çağırmak için kullanabilirsiniz. Ancak bu durum,BoxWithConstraintsdüzen aşamasına kadar kompozisyonu ertelediği için bazı maliyetlere yol açar. Bu kısıtlamalar bilindiğinde düzen sırasında daha fazla iş yapılması gerekir.
@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
Ekran alanından yararlanan bir composable işlevi uygularken verileri mevcut ekran boyutunun yan etkisi olarak yüklemek isteyebilirsiniz.
Ancak bu işlem, verilerin uygun şekilde oluşturulması için composable'lara aktarılıp sağlandığı tek yönlü veri akışı ilkesine aykırıdır. Birleştirilebilir öğeye, içeriğin bir kısmı her zaman kullanılmayacak olsa bile her ekran boyutu için yeterli içerik sağlamak üzere yeterli 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ğinden yola çıkarak description değerinin her zaman Card öğesine iletildiğini unutmayın. description yalnızca genişlik izin verdiğinde kullanılsa da Card, mevcut genişlikten bağımsız olarak her zaman description gerektirir.
Her zaman yeterli içerik iletmek, uyarlanabilir düzenleri daha az durum bilgisi içeren hale getirerek basitleştirir ve ekran boyutları arasında geçiş yaparken (pencere boyutu değiştirme, yön değişikliği veya cihazı katlama ve açma nedeniyle oluşabilir) yan etkilerin tetiklenmesini önler.
Bu ilke, düzen değişikliklerinde durumun korunmasına da olanak tanır. Tüm ekran boyutlarında kullanılmayabilecek bilgileri taşıyarak düzen boyutu değiştiğinde uygulama durumunu koruyabilirsiniz.
Örneğin, ekran yeniden boyutlandırıldığında düzenin içeriği gizleme ve gösterme arasında geçiş yapmasına neden olan durumlarda uygulama durumunun korunması için bir showMore boolean işareti 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'daki uyarlanabilir düzenler hakkında daha fazla bilgi edinmek için aşağıdaki kaynaklara bakı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ından yararlanacak şekilde uyarlayan bir uygulamanın nasıl tasarlanacağını gösteriyor.
- 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 boyutu için Android kullanıcı arayüzleri oluşturma
- Form Faktörleri | Android Dev Summit '22