Görünümler'den Compose'a geçiş tamamen kullanıcı arayüzüyle ilgili olsa da birçok güvenli ve artımlı bir taşıma gerçekleştirmek için dikkate alınması gereken noktalar vardır. Bu taşıma işlemi sırasında göz önünde bulundurulması gereken bazı Compose'a görüntüleme tabanlı uygulama.
Uygulamanızın temasını taşıma
Android uygulamalarında tema oluşturmak için önerilen tasarım sistemi Materyal Tasarım'dır.
Görünüm tabanlı uygulamalarda, Materyal'in üç sürümü mevcuttur:
- Materyal Tasarım 1,
AppCompat kitaplığı (ör.
Theme.AppCompat.*
) - Materyal Tasarım 2,
MDC-Android
kütüphane (ör.
Theme.MaterialComponents.*
) - Materyal Tasarım 3,
MDC-Android
kütüphane (ör.
Theme.Material3.*
)
Oluşturma uygulamaları için Material'ın iki sürümü vardır:
- Materyal Tasarım 2,
Materyal Oluşturma kitaplığı
(ör.
androidx.compose.material.MaterialTheme
) - Compose Material 3 kitaplığını (ör.
androidx.compose.material3.MaterialTheme
) kullanan Material Design 3
Uygulamanızın tasarım sistemiyse en yeni sürümü (Material 3) kullanmanızı öneririz kişi bunu yapabilecek durumda olacaktır. Her iki Görünüm için de taşıma kılavuzları mevcut ve Oluştur:
- Görünümlerde 1. Malzeme ile 2. Malzeme Arasında
- Görünümlerde 2. Malzeme ile 3. Malzeme Arasında
- Oluştur'da 2. Malzeme'den 3. Malzeme'ye
Materyalin hangi sürümüne sahip olursa olsun Compose'da yeni ekran oluştururken
Kullandığınız tasarımda, herhangi bir uygulamadan önce MaterialTheme
uyguladığınızdan emin olun
Compose Material kitaplıklarından kullanıcı arayüzü yayınlayan composable'lar. Materyal
bileşenler (Button
, Text
vb.), mevcut bir MaterialTheme
değerine bağlıdır
ve bunlar olmadan davranışları tanımsızdır.
Tümü
Jetpack Compose örnekleri
MaterialTheme
temel alınarak oluşturulmuş özel bir Oluştur teması kullanın.
Daha fazla bilgi edinmek için Compose'daki tasarım sistemleri ve XML temalarını Compose'a taşıma sayfalarına göz atın.
Navigasyon
Uygulamanızda Navigasyon bileşenini kullanıyorsanız Oluşturma ile Gezinme - Birlikte Çalışabilirlik ve Daha fazla bilgi için Jetpack Gezinme'yi Gezinme Oluşturma'ya taşıyın.
Karma Oluştur/Görüntülemeler kullanıcı arayüzünüzü test etme
Uygulamanızın bazı bölümlerini Compose'a taşıdıktan sonra test, uygulamanızın hiçbir şeyi düzeltmediniz.
Bir etkinlik veya parça Oluşturma özelliğini kullandığında,
createAndroidComposeRule
ActivityScenarioRule
tercih edebilirsiniz. createAndroidComposeRule
entegrasyonu
ActivityScenarioRule
ve ComposeTestRule
ile Oluşturma ve oluşturma işlemlerini test etmenize olanak tanır.
Kodu aynı anda görüntüleyebilirsiniz.
class MyActivityTest { @Rule @JvmField val composeTestRule = createAndroidComposeRule<MyActivity>() @Test fun testGreeting() { val greeting = InstrumentationRegistry.getInstrumentation() .targetContext.resources.getString(R.string.greeting) composeTestRule.onNodeWithText(greeting).assertIsDisplayed() } }
Test hakkında daha fazla bilgi edinmek için Oluşturma düzeninizi test etme konusuna bakın. Kullanıcı arayüzü test çerçeveleriyle birlikte çalışabilirlik için Espresso ile birlikte çalışabilirlik ve UiAutomator ile birlikte çalışabilirlik başlıklı makalelere bakın.
Compose'u mevcut uygulama mimarinizle entegre etme
Tek Yönlü Veri Akışı (UDF) mimarisi desenleri de Compose ile uyumlu. Uygulama, (MVP) gibi mimari kalıplarına bağlı olarak değil, Compose'dan önce veya kullanım sırasında kullanıcı arayüzünün bu bölümünü UDF'ye taşıyın.
Oluşturma'da ViewModel
kullanma
Mimari Bileşenleri
ViewModel
kitaplığındaki
Herhangi bir composable'dan ViewModel
viewModel()
fonksiyonuna ilişkin Oluşturma ve diğer kitaplıklar bölümünde açıklanmıştır.
Oluştur'u kullanırken aynı ViewModel
türünün
ViewModel
öğeleri View yaşam döngüsü kapsamlarını izlediğinden farklı composable'lar kullanılabilir. Kapsam, ana makine etkinliği, parça veya Gezinme kitaplığı kullanılıyorsa gezinme grafiği olacaktır.
Örneğin, composable'lar bir etkinlik içinde barındırılıyorsa viewModel()
her zaman
yalnızca etkinlik tamamlandığında silinen aynı örneği döndürür.
Aşağıdaki örnekte, aynı kullanıcı ("user1") iki kez selamlanmıştır çünkü
aynı GreetingViewModel
örneği
yardımcı olur. Oluşturulan ilk ViewModel
örnek, diğer
composables.
class GreetingActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MaterialTheme { Column { GreetingScreen("user1") GreetingScreen("user2") } } } } } @Composable fun GreetingScreen( userId: String, viewModel: GreetingViewModel = viewModel( factory = GreetingViewModelFactory(userId) ) ) { val messageUser by viewModel.message.observeAsState("") Text(messageUser) } class GreetingViewModel(private val userId: String) : ViewModel() { private val _message = MutableLiveData("Hi $userId") val message: LiveData<String> = _message } class GreetingViewModelFactory(private val userId: String) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create(modelClass: Class<T>): T { return GreetingViewModel(userId) as T } }
Gezinme grafikleri olarak ViewModel
öğelerinin kapsamı,
bir gezinme grafiğindeki hedefte ViewModel
öğesinin farklı bir örneği vardır.
Bu durumda ViewModel
, hedefin yaşam döngüsünü kapsar ve
hedef geri yığından kaldırıldığında silinir.
Aşağıdaki örnekte, kullanıcı Profil ekranına gittiğinde yeni bir
GreetingViewModel
örneği oluşturuldu.
@Composable fun MyApp() { NavHost(rememberNavController(), startDestination = "profile/{userId}") { /* ... */ composable("profile/{userId}") { backStackEntry -> GreetingScreen(backStackEntry.arguments?.getString("userId") ?: "") } } }
Doğru bilgi kaynağı
Kullanıcı arayüzünün bir bölümünde Oluştur'u kullandığınızda Oluştur ve Görüntüleme sistem kodunun veri paylaşması gerekebilir. Mümkünse
bu paylaşılan durumu UDF en iyi uygulamalarını izleyen başka bir sınıfa ekleyin.
her iki platform tarafından kullanılan örneğin, ViewModel
Paylaşılan verilerin veri güncellemeleri çıkarmasını sağlar.
Ancak paylaşılacak veriler değişkense veya bir kullanıcı arayüzü öğesine sıkıca bağlıysa bu her zaman mümkün olmayabilir. Bu durumda bir sistem kabul etmesi ve bu sistemin, veri güncellemelerini diğer sistemle paylaşması gerekir. Genel kural olarak, doğruluk kaynağının sahibi kullanıcı arayüzü hiyerarşisinin köküne daha yakın olan öğe olmalıdır.
Doğru bilgi kaynağı olarak yazın
Şunu kullanın:
SideEffect
composable'ı kullanarak Compose durumunu Compose dışı koda yayınlayabilirsiniz. Bu durumda,
veri kaynağı, durum güncellemeleri gönderen bir composable'da tutulur.
Örneğin, analiz kitaplığınız, sonraki tüm analiz etkinliklerine özel meta veriler (bu örnekte kullanıcı özellikleri) ekleyerek kullanıcı kitlenizi segmentlere ayırmanıza olanak tanıyabilir. Mevcut kullanıcının kullanıcı türünü analiz kitaplığınıza iletmek için değerini güncellemek üzere SideEffect
kullanın.
@Composable fun rememberFirebaseAnalytics(user: User): FirebaseAnalytics { val analytics: FirebaseAnalytics = remember { FirebaseAnalytics() } // On every successful composition, update FirebaseAnalytics with // the userType from the current User, ensuring that future analytics // events have this metadata attached SideEffect { analytics.setUserProperty("userType", user.userType) } return analytics }
Daha fazla bilgi için Oluşturma'daki yan etkiler başlıklı makaleyi inceleyin.
Bilgi kaynağı olarak sistemi göster
Görüntüleme sistemi eyaletin sahibiyse ve Oluştur ile paylaşıyorsa şunu öneririz:
durumu, iş parçacığı açısından güvenli hâle getirmek üzere mutableStateOf
nesne içine sarmalarsınız.
Oluştur'u tıklayın. Bu yaklaşımı kullanırsanız composable işlevler basitleştirilmiştir çünkü bu
artık veri kaynağına sahip değiller, ancak Görünüm sisteminin
durumu kullanan Görünümler de dahildir.
Aşağıdaki örnekte, CustomViewGroup
bir TextView
ve bir
İçinde TextField
composable bulunan ComposeView
. TextView
özelliğinin gösterilmesi gerekiyor
Kullanıcının TextField
içinde yazdığı içeriğin içeriği.
class CustomViewGroup @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = 0 ) : LinearLayout(context, attrs, defStyle) { // Source of truth in the View system as mutableStateOf // to make it thread-safe for Compose private var text by mutableStateOf("") private val textView: TextView init { orientation = VERTICAL textView = TextView(context) val composeView = ComposeView(context).apply { setContent { MaterialTheme { TextField(value = text, onValueChange = { updateState(it) }) } } } addView(textView) addView(composeView) } // Update both the source of truth and the TextView private fun updateState(newValue: String) { text = newValue textView.text = newValue } }
Paylaşılan kullanıcı arayüzü taşınıyor
Kademeli olarak Compose'a geçiş yapıyorsanız paylaşılan kullanıcı arayüzünü kullanmanız gerekebilir
öğelerini görüntüleme ve yönetme işlemlerini yapabilirsiniz. Örneğin, uygulamanızda
özel CallToActionButton
bileşenini, Oluşturduğunuz
ve görüntülemeye dayalı ekranlar.
Oluşturma'da, paylaşılan kullanıcı arayüzü öğeleri, XML kullanılarak stilize edilmiş veya özel görünümlü olup olmadığına bakılmaksızın uygulama genelinde yeniden kullanılabilen bileşenler haline gelir. Örneğin,
Örneğin, şuna özel çağrınız için bir CallToActionButton
composable:
işlem Button
bileşeni.
Görünüme dayalı ekranlarda composable'ı kullanmak için, şu özelliklere sahip özel bir görünüm sarmalayıcı oluşturun:
AbstractComposeView
ile başlayıp uzanıyor. Geçersiz kılınmış Content
composable'da,
oluşturduğunuz composable'ı
aşağıdaki örneğe bakın:
@Composable fun CallToActionButton( text: String, onClick: () -> Unit, modifier: Modifier = Modifier, ) { Button( colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.secondary ), onClick = onClick, modifier = modifier, ) { Text(text) } } class CallToActionViewButton @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = 0 ) : AbstractComposeView(context, attrs, defStyle) { var text by mutableStateOf("") var onClick by mutableStateOf({}) @Composable override fun Content() { YourAppTheme { CallToActionButton(text, onClick) } } }
Oluşturulabilir parametrelerin, özel
görünüm. Bu da özel CallToActionViewButton
görünümünü şişirebilir ve kullanılabilir hale getirir,
geleneksel bir görünüm gibi. Görünüm Bağlama ile bunun bir örneğini görebilirsiniz
aşağıda bulabilirsiniz:
class ViewBindingActivity : ComponentActivity() { private lateinit var binding: ActivityExampleBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityExampleBinding.inflate(layoutInflater) setContentView(binding.root) binding.callToAction.apply { text = getString(R.string.greeting) onClick = { /* Do something */ } } } }
Özel bileşende değişken durum varsa Doğruluk durumu kaynağı bölümüne bakın.
Sunudan bölme durumuna öncelik ver
Geleneksel olarak View
, durum bilgilidir. View
, şu alanları yönetir:
Ne gösterileceğini ve nasıl gösterileceğini açıklayın. Google Takvim widget'ını
View
öğesini Compose'a dönüştürüyorsanız oluşturulan verileri
durum kaldırma bölümünde daha ayrıntılı olarak açıklandığı gibi tek yönlü bir veri akışı elde etmek.
Örneğin, bir View
,visibility
görünmez veya kaybolabilir. Bu, View
öğesinin doğal bir özelliğidir. Bu sırada
diğer kod parçaları View
öğesinin görünürlüğünü değiştirebilir, yalnızca View
ne olduğunu gerçekten biliyor. Bunu sağlamanın mantığı,
bir View
görünür olduğunda hataya açık olabilir ve genellikle View
ile bağlantılıdır
kendisi.
Buna karşın Compose, tamamen farklı composable'ları görüntülemeyi kolaylaştırır (kotlin'de koşullu mantığı kullanarak):
@Composable fun MyComposable(showCautionIcon: Boolean) { if (showCautionIcon) { CautionIcon(/* ... */) } }
CautionIcon
web sitesinin tasarımı gereği, neden gösterildiğini bilmesine veya bununla ilgilenmesine gerek yoktur.
visibility
kavramı da yoktur. O ya bestededir, ya da
değildir.
Durum yönetimi ile sunum mantığını net bir şekilde birbirinden ayırarak, durumu kullanıcı arayüzüne dönüştürme olarak görüntüleme şeklinizi özgürce değiştirebilirsiniz. Olmak composable'ı yeniden kullanılabilir hâle getirdiği için, eyalet sahipliği daha esnektir.
Kapsüllenmiş ve yeniden kullanılabilir bileşenleri tanıtın
View
öğelerinin genellikle nerede bulunduklarına dair bir fikri vardır: Bir Activity
içinde,
Dialog
, Fragment
veya başka bir View
hiyerarşisinin içinde başka bir yerde. Çünkü
genellikle statik düzen dosyalarından şişirilirler. Bu dosya, bir
View
genelde çok katıdır. Bu, daha sıkı bağlantı sağlar ve
bir View
değerinin değiştirilmesi veya yeniden kullanılması daha zordur.
Örneğin, özel bir View
belirli bir özelliğin alt görünümüne sahip olduğunu
belirli bir kimlikle yazmanızı ve özelliklerini doğrudan
eyleme dökülebilir. Bu, söz konusu View
öğelerini birbirine sıkıca bağlar: Özel View
, alt öğeyi bulamadığı takdirde kilitlenebilir veya bozulabilir. Alt öğe de özel View
üst öğesi olmadan büyük olasılıkla yeniden kullanılamaz.
Bu, yeniden kullanılabilir composable'larla Compose'da daha az sorun yaşanır. Ebeveynler durumu ve geri çağırma işlevlerini kolayca belirtebilir. Böylece, kullanılacakları yeri tam olarak bilmek zorunda kalmadan yeniden kullanılabilir bileşenler yazabilirsiniz.
@Composable fun AScreen() { var isEnabled by rememberSaveable { mutableStateOf(false) } Column { ImageWithEnabledOverlay(isEnabled) ControlPanelWithToggle( isEnabled = isEnabled, onEnabledChanged = { isEnabled = it } ) } }
Yukarıdaki örnekte üç parça da daha kapsüllenmiş ve daha az ilişkilidir:
ImageWithEnabledOverlay
uygulamasının yalnızca geçerliisEnabled
öğesinin ne olduğunu bilmesi gerekiyor belirtin.ControlPanelWithToggle
varlığının bilmesi gerekmez veya nasıl kontrol edilebildiğini bile fark edebilirsiniz.ControlPanelWithToggle
,ImageWithEnabledOverlay
adlı cihazın mevcut olduğunu bilmiyor.isEnabled
, sıfır, bir veya daha fazla şekilde gösterilebilir veControlPanelWithToggle
adlı kullanıcının değişmesi gerekmez.Üst öğe için,
ImageWithEnabledOverlay
öğesinin ne kadar derinlemesine iç içe yerleştirilmiş olduğu önemli değildir veyaControlPanelWithToggle
. Bu çocuklar, değişiklikler için animasyon başka çocuklara içerik aktarmaktan bahsedeceğiz.
Bu kalıp kontrolün ters çevirmesi olarak bilinir. Daha fazla bilgi edinmek için
hakkındaki CompositionLocal
belgeleri inceleyebilirsiniz.
Ekran boyutu değişikliklerini işleme
Farklı pencere boyutları için farklı kaynaklara sahip olmak, projenizin
duyarlı View
düzenleri oluşturabilirsiniz. Nitelikli kaynaklar bir seçenek olarak
ekran düzeyinde düzen kararları için Compose'u kullanmak çok daha kolay
normal koşullu mantıkla tamamen koddan
bir araya getirmenizi sağlar. Daha fazla bilgi edinmek için Pencere boyutu sınıfları başlıklı makaleyi inceleyin.
Ayrıca, Farklı ekran boyutlarını destekleme başlıklı makaleyi inceleyin. Compose'un uyarlanabilir kullanıcı arayüzleri oluşturmak için sunduğu teknikleri öğrenin.
Görünümler ile iç içe geçmiş kaydırma
Sayfalar arasında iç içe kaydırmayı etkinleştirme hakkında daha fazla bilgi için kaydırılabilir görünüm öğeleri ve kaydırılabilir composable'lar, her iki yönde iç içe yerleştirilmiş. sesli oku İç içe kaydırma birlikte çalışabilirliği.
RecyclerView
uygulamasında oluştur
RecyclerView
içindeki derlenebilirler, RecyclerView
sürümünden bu yana iyi performans gösteriyor
1.3.0-alpha02. Bu avantajlardan yararlanmak için RecyclerView
'ın en az 1.3.0-alpha02 sürümünü kullandığınızdan emin olun.
WindowInsets
, Görünümler ile birlikte çalışabilir
Ekranınızda hem Görünümler hem de görünümler olduğunda varsayılan değerleri geçersiz kılmanız gerekebilir. Kodu aynı hiyerarşide oluşturun. Bu durumda, konu hakkında ek öğeleri hangisinin tüketmesi gerektiği ve hangisinin yoksayılması gerektiği.
Örneğin, en dıştaki düzeniniz bir Android View düzeniyse
insetleri Görüntüle sisteminde tüketme ve Oluşturma için bunları yoksayma.
Alternatif olarak, en dıştaki düzeniniz bir composable ise
inset'leri ekleyin ve AndroidView
composable'ı buna uygun şekilde yerleştirin.
Varsayılan olarak her ComposeView
,
WindowInsetsCompat
tüketim seviyesi. Bu varsayılan davranışı değiştirmek için
ComposeView.consumeWindowInsets
Hedef: false
.
Daha fazla bilgi için E-posta Yazma'da WindowInsets
dokümanlarını okuyun.
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir
- Emoji gösterme
- Compose'da Materyal Tasarım 2
- Compose'da pencere içleri