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ına tema eklemek 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
) - Materyal Tasarım 3,
Oluşturma Materyal 3 kitaplığı
(ör.
androidx.compose.material3.MaterialTheme
)
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ümler'de Materyal 1'den Materyal 2'ye
- Görünümler'de Materyal 2'den Materyal 3'e
- Compose'da Materyal 2'den Materyal 3'e
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şturma/Görünümler 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. Örneğin, Kullanıcı arayüzü test çerçeveleriyle birlikte çalışabilirlik hakkında daha fazla bilgi için bkz. Espresso ile birlikte çalışabilirlik ve UiAutomator ile birlikte çalışabilirlik.
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.
Compose'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. İlgili içeriği oluşturmak için kullanılan
kapsam, ana makine etkinliği, parça veya gezinme grafiği olur.
Navigasyon kitaplığı kullanılı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ğı
Oluştur'u kullanıcı arayüzünün bir bölümünde kullandığınızda
View sistem kodunun verileri paylaşması gerekir. 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
veri güncellemeleri ortaya çıkarmak için,
paylaşılan verilerin üretilmesine neden olabilir.
Ancak, paylaşılacak veriler değişkense veya bir kullanıcı arayüzü öğesine sıkı sıkıya bağlı. Bu durumda bir sistem kabul etmesi ve bu sistemin, veri güncellemelerini diğer sistemle paylaşması gerekir. Kullanıcı genel kurala göre, doğru kaynağın, ilgili öğeye ait olması kullanıcı arayüzü hiyerarşisinin köküne daha yakındı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 kullanıcılarınızı segmentlere ayırmanıza
özel meta veriler ekleyerek nüfusu (bu örnekte kullanıcı özellikleri)
ve sonraki tüm Analytics etkinliklerine
katkıda bulunur. Verinin kullanıcı türünü
analiz kitaplığınıza eklemek için SideEffect
değerini 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 Compose'da yan etkiler bölümüne bakın.
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.
Compose'da paylaşılan kullanıcı arayüzü öğeleri,
uygulamasında, XML kullanılarak stil verilen öğenin veya özel bir görünüm olmasından bağımsız olarak uygulanır. Ö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şen değişken durum içeriyorsa doğru.
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 işlem, söz konusu View
öğelerini sıkı bir şekilde birleştirir: özel View
çocuğu bulamazsa kilitlenebilir veya bozulabilir, çocuk da büyük olasılıkla bulamaz.
özel View
üst öğesi olmadan yeniden kullanılabilir.
Bu, yeniden kullanılabilir composable'larla Compose'da daha az sorun yaşanır. Ebeveynler şunları yapabilir: durumu ve geri çağırmaları kolayca belirtebilir, böylece yeniden kullanılabilir composable'lar yazabilirsiniz ve nerede kullanılacaklarını bilmek zorunda kalmadan.
@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üzenle ilgili kararlar almak için Compose'u kullanmak çok daha
düzenlerini normal koşullu mantıkla tamamen kodda tutar. 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. Şu sürümün en az 1.3.0-alpha02 sürümünü kullandığınızdan emin olun:
Bu avantajları görmek için RecyclerView
.
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