Mencoba Jetpack Compose dalam pertempuran?

Akhirnya, saatnya telah tiba ketika Anda tidak perlu membangun Android Studio sendiri untuk mencoba kerangka UI deklaratif baru untuk Android. Jetpack Compose sekarang tersedia sebagai Pratinjau Dev pertama di Maven Repository Google. Dengan berita ini, hari Senin pagi saya dimulai. Dan segera ada keinginan untuk melihat seperangkat alat apa yang telah mereka tunggu-tunggu.



Saya memutuskan untuk memulai kenalan saya segera dengan upaya untuk memperkenalkannya ke dalam proyek kesayangan yang diterbitkan di Google Play. Apalagi di dalamnya sudah lama saya ingin membuat halaman "Tentang aplikasi". Pada artikel ini saya akan berbicara tentang komponen utama dan langkah-langkah koneksi Compose:


  1. Koneksi Ketergantungan
  2. Tema dan gaya. Integrasi dengan yang ada dalam proyek.
  3. Tes aksesibilitas dan UI.
  4. Komponen utama dan analog dari pewaris View.
  5. Bekerja dengan Negara.

Koneksi Ketergantungan


Untuk memulai, saya memperbarui studio dari 3,5 ke 3.5.1 (sia-sia), menambahkan dependensi dasar. Daftar lengkap dapat dilihat dalam artikel oleh Cyril .


// build.gradle ext.compose_version= '0.1.0-dev01' //build.gradle  dependencies{ ... implementation "androidx.compose:compose-runtime:$compose_version" kapt "androidx.compose:compose-compiler:$compose_version" implementation "androidx.ui:ui-layout:$compose_version" implementation "androidx.ui:ui-android-text:$compose_version" implementation "androidx.ui:ui-text:$compose_version" implementation "androidx.ui:ui-material:$compose_version" } 

Dan kemudian saya mencoba untuk mengumpulkan semua ini karena versi Firebase yang tersebar. Setelah itu saya bertemu dengan Compose rintangan:


 app/src/main/AndroidManifest.xml Error: uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [androidx.ui:ui-layout:0.1.0-dev01] .../ui-layout-0.1.0-dev01/AndroidManifest.xml as the library might be using APIs not available in 16 Suggestion: use a compatible library with a minSdk of at most 16, or increase this project's minSdk version to at least 21, or use tools:overrideLibrary="androidx.ui.layout" to force usage (may lead to runtime failures) 

Ya, Tulisan hanya tersedia dengan minSdk 21 (Lolipop). Mungkin ini adalah tindakan sementara, tetapi diharapkan untuk mendukung versi OS sebelumnya.


Tapi itu belum semuanya. Tulis karya tentang Refleksi, alih-alih Plugin Komplin Kotlin, seperti yang dinyatakan sebelumnya, misalnya, di sini . Oleh karena itu, agar semuanya dapat dimulai, Anda perlu menambahkan Refleksi Kotlin juga tergantung pada:


 implementation "org.jetbrains.kotlin:kotlin-reflect" 

Nah, untuk pencuci mulut. Tulis dp mengimplementasikan fungsi ekstensi untuk Int, Long, Float, yang ditandai dengan kata kunci sebaris. Ini dapat menyebabkan kesalahan kompilasi baru:


 Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option * https://stackoverflow.com/questions/48988778/cannot-inline-bytecode-built-with-jvm-target-1-8-into-bytecode-that-is-being-bui 

Untuk menyelesaikannya, Anda perlu mendaftarkan versi JVM untuk Kotlin secara eksplisit:


 android { … kotlinOptions { jvmTarget = "1.8" } } 

Sepertinya hanya itu saja. Jauh lebih mudah daripada membangun studio sendiri)


Mari kita coba menjalankan Hello World (juga dari artikel Cyril, tetapi, tidak seperti dia, tambahkan Compose inside Fragment). Tata letak untuk fragmen adalah FrameLayout kosong.


 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val fragmentView = inflater.inflate(R.layout.fragment_about, container, false) (fragmentView as ViewGroup).setContent { Hello("Jetpack Compose") } return fragmentView } @Composable fun Hello(name: String) = MaterialTheme { FlexColumn { inflexible { // Item height will be equal content height TopAppBar<MenuItem>( // App Bar with title title = { Text("Jetpack Compose Sample") } ) } expanded(1F) { // occupy whole empty space in the Column Center { // Center content Text("Hello $name!") // Text label } } } } 

Kami mulai, layar berikut ini ternyata:


gambar

Karena fakta bahwa Composable menggunakan tema Material default, kami mendapat AppBar ungu. Yah, dan, seperti yang diharapkan, sama sekali tidak konsisten dengan tema aplikasi yang gelap:


gambar

Mari kita coba menyelesaikannya.


Tema dan gaya. Integrasi dengan yang ada dalam proyek.


Untuk menggunakan style yang ada di dalam Composable, kami meneruskannya di dalam konstruktor MaterialTheme:


 @Composable fun Hello(name: String) = MaterialTheme(colors = MaterialColors( primary = resolveColor(context, R.attr.colorPrimary, MaterialColors().primary), secondary = resolveColor(context, R.attr.colorSecondary, MaterialColors().secondary), onBackground = resolveColor(context, R.attr.textColor, MaterialColors().onBackground) )){...} 

MaterialTheme sendiri terdiri dari dua bagian: MaterialColors dan MaterialTypography.
Untuk mengatasi warna, saya menggunakan pembungkus atas gaya:


 private fun resolveColor(context: Context?, @AttrRes attrRes: Int, colorDefault: Color) = context?.let { Color(resolveThemeAttr(it, attrRes).data.toLong()) } ?: colorDefault private fun resolveThemeAttr(context: Context, @AttrRes attrRes: Int): TypedValue { val theme = context.theme val typedValue = TypedValue() theme.resolveAttribute(attrRes, typedValue, true) return typedValue } 

Pada tahap ini, AppBar akan berubah menjadi hijau. Tetapi untuk mengecat teks, Anda perlu melakukan satu tindakan lagi:


 Text("Hello $name!", style = TextStyle(color = +themeColor { onBackground })) 

Tema diterapkan ke widget menggunakan operasi plus unary. Kami masih akan melihatnya ketika bekerja dengan Negara.


Sekarang layar baru terlihat seragam dengan sisa aplikasi di kedua varian tema:


gambar

Tulis juga menemukan file DarkTheme.kt di sumber, fungsi yang dapat digunakan untuk menentukan berbagai pemicu untuk mengaktifkan tema gelap pada Android P dan 10.


Tes aksesibilitas dan UI.


Sampai layar mulai tumbuh dengan elemen baru, mari kita lihat tampilannya di Inspektur Tata Letak dan dengan tampilan batas elemen dalam Mode Dev dihidupkan:



gambar

Di sini kita akan melihat FrameLayout, di dalamnya hanya AndroidComposeView. Alat yang ada untuk pengujian Accebility dan UI tidak lagi berlaku? Mungkin alih-alih sekarang ada perpustakaan baru: androidx.ui:ui-test .


Komponen utama dan analog dari pewaris View.


Sekarang mari kita coba membuat layar sedikit lebih informatif. Pertama, ubah teks, tambahkan tombol yang mengarah ke halaman aplikasi di Google Play, dan gambar dengan logo. Saya akan segera menunjukkan kode dan apa yang terjadi:


 @Composable fun AboutScreen() = MaterialTheme(...) { FlexColumn { inflexible { TopAppBar<MenuItem>(title = { Text(getString(R.string.about)) }) } expanded(1F) { VerticalScroller { Column { Image() Title() MyButton() } } } } } private fun Image() { Center { Padding(16.dp) { Container( constraints = DpConstraints( minWidth = 96.dp, minHeight = 96.dp ) ) { imageFromResource(resources, R.drawable.ic_launcher) } } } } private fun Title() { Center { Padding(16.dp) { Text(getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME, style = TextStyle(color = +themeColor { onBackground })) } } } private fun MyButton() { Center { Padding(16.dp) { Button(getString(R.string.about_button), onClick = { openAppInPlayStore() }) } } } 

gambar

Prinsip dasar komposisi widget tidak berubah sejak kemunculan pertama sumber Menulis .


Dari yang menarik:


  • Fungsi untuk menampilkan elemen individual tidak harus dianotasi dengan @Composable.
  • Hampir semua properti untuk widget berubah menjadi widget terpisah (Pusat alih-alih android: gravitasi, Padding, bukan android: margin, ...)
  • Saya tidak dapat menampilkan gambar dari drawables.
  • Parameter onClick dari tombol bukan yang terakhir, karena itu tidak mungkin untuk meneruskannya sebagai lambda tanpa nama eksplisit, yang akan tampak lebih logis:
     Button(β€œText"){ openAppInPlayStore() } 

Sekarang mari kita melihat ViewGroup utama yang ada dan mencoba mencari analog di Compose.


Alih-alih FrameLayout, Anda bisa menggunakan Stack. Semuanya sederhana di sini: widget anak tumpang tindih dan diposisikan tergantung pada fungsi yang digunakan untuk lampiran: selaras, diposisikan atau diperluas.


LinearLayout segera diganti oleh dua widget: Kolom dan Baris alih-alih menggunakan parameter orientasi android:. Mereka, pada gilirannya, mengandung FlexColumn dan FlexRow dengan lapisan fungsi tidak fleksibel di atas subtree bersarang. Nah, FlexColumn dan FlexRow sendiri dibangun di atas Flex dengan orientation = LayoutOrientation.Vertical parameter orientation = LayoutOrientation.Vertical atau Horizontal .


Hirarki serupa untuk widget FlowColumn, FlowRow, dan Flow. Perbedaan utama mereka: jika konten tidak muat dalam satu kolom atau baris, yang berikutnya akan ditarik berikutnya, dan widget yang tertanam akan "mengalir" di sana. Sulit bagi saya untuk membayangkan tujuan sebenarnya dari widget ini.


Efek ScrollView dicapai dengan menempatkan Kolom atau Baris di dalam VerticalScroller atau HorizontalScroller. Mereka berdua menulis di dalam Scroller, melewati parameter isVertical = true atau false .


Dalam mencari analog untuk ConstraintLayout, atau setidaknya RelativeLayout menemukan widget Tabel baru. Saya mencoba menjalankan kode sampel di aplikasi saya: DataTableSamples.kt . Tetapi, karena saya tidak mencoba menyederhanakan contoh, itu tidak berhasil untuk membuatnya bekerja.


gambar

Bekerja dengan Negara


Salah satu inovasi kerangka kerja yang paling dinanti adalah kesiapannya untuk digunakan dalam arsitektur searah yang dibangun atas dasar satu negara. Dan ini seharusnya memperkenalkan anotasi @Model ke tag kelas yang menyediakan Negara untuk rendering UI.
Pertimbangkan sebuah contoh:


 data class DialogVisibleModel(val visible: Boolean, val dismissPushed: Boolean = false) ... @Composable fun SideBySideAlertDialogSample() { val openDialog = +state { DialogVisibleModel(true) } Button(text = "Ok", onClick = { openDialog.value = DialogVisibleModel(true) }) if (openDialog.value.visible) { AlertDialog( onCloseRequest = { // Because we are not setting openDialog.value to false here, // the user can close this dialog only via one of the buttons we provide. }, title = { Text(text = "Title") }, text = { Text("This area typically contains the supportive text" + " which presents the details regarding the Dialog's purpose.") }, confirmButton = { Button("Confirm", onClick = { openDialog.value = DialogVisibleModel(false) }) }, dismissButton = { if (!openDialog.value.dismissPushed) Button("Dismiss", onClick = { openDialog.value = DialogVisibleModel(true, true) }) else { //hidden } }, buttonLayout = AlertDialogButtonLayout.SideBySide ) } } 

Ini menciptakan kelas data untuk model keadaan, dan tidak harus ditandai dengan penjelasan @Model.
Status awal itu sendiri dibuat di dalam fungsi @Composable menggunakan status +.
Visibilitas dialog ditentukan oleh properti terlihat dari model yang diperoleh dengan memanggil properti nilai.
Properti ini juga dapat diatur ke objek abadi yang baru, seperti yang terjadi pada klik pada kedua tombol. Yang pertama menyembunyikan dirinya sendiri, yang kedua - menutup dialog. Dialog dapat dibuka kembali dengan mengklik tombol Ok, didefinisikan di dalam fungsi @Composable yang sama.
Saat mencoba membuat status di luar fungsi ini, terjadi kesalahan:
java.lang.IllegalStateException: Composition requires an active composition context.
Konteksnya dapat diperoleh dengan menetapkan nilai fungsi setContent {} di onCreateView, tetapi bagaimana menggunakannya, misalnya, di Presenter atau kelas lain selain Fragmen atau Aktivitas, untuk mengubah keadaan masih belum jelas.


gambar

Ini menyimpulkan ulasan kami tentang pustaka Tulis Jetpack baru. Kerangka kerja membenarkan namanya secara arsitektur, menggantikan semua warisan, yang begitu tidak nyaman dalam hierarki Tampilan, dengan komposisi. Masih terlalu banyak pertanyaan tentang bagaimana analog dari ViewGroup yang lebih kompleks akan diimplementasikan, seperti ConstraintLayout dan RecyclerView; tidak cukup dokumentasi dan pratinjau.


Sangat jelas bahwa Compose tidak siap untuk digunakan bahkan dalam aplikasi tempur kecil.


Tapi ini hanya versi pertama dari Pratinjau Pratinjau. Akan menarik untuk mengamati perkembangan konsep bekerja dengan Negara dan perpustakaan dari masyarakat berdasarkan Compose.


Jika Anda menemukan contoh kode yang lebih berhasil, atau dokumentasi untuk kasus yang tidak dapat saya dapatkan, silakan tulis di komentar.

Source: https://habr.com/ru/post/id471670/


All Articles