1. Sebelum memulai
Codelab ini memberikan petunjuk praktis tentang dasar-dasar penerapan operasi tarik lalu lepas untuk Compose. Anda akan mempelajari cara mengaktifkan tampilan untuk ditarik dan dilepas, baik di dalam aplikasi maupun di berbagai aplikasi. Anda akan mempelajari cara menerapkan operasi tarik lalu lepas dalam aplikasi dan bahkan di berbagai aplikasi.
Prasyarat
Untuk menyelesaikan codelab ini, Anda memerlukan:
- Pengalaman membangun aplikasi Android
- Pengalaman dengan Jetpack Compose dan Pengubah
Yang akan Anda lakukan
Membuat aplikasi sederhana yang:
- Mengonfigurasi composable agar dapat ditarik menggunakan pengubah dragAndDropSource
- Mengonfigurasi composable untuk menjadi target lepas menggunakan pengubah dragAndDropTarget
Yang akan Anda butuhkan
- Android Studio Jellyfish atau yang lebih baru
- Perangkat Android atau emulator
2. Peristiwa tarik lalu lepas
Operasi tarik lalu lepas dapat dilihat sebagai peristiwa 4 tahap, yaitu sebagai berikut
- Dimulai : Sistem memulai operasi tarik lalu lepas sebagai respons terhadap gestur tarik pengguna.
- Melanjutkan : Pengguna terus menarik.
- Berakhir : Pengguna melepaskan operasi tarik di composable target lepas
- Tersedia : Sistem mengirimkan sinyal untuk mengakhiri operasi tarik lalu lepas.
Sistem mengirim peristiwa tarik di objek DragEvent
. Objek DragEvent
dapat berisi data berikut
ActionType
: Nilai tindakan peristiwa berdasarkan peristiwa siklus proses dari peristiwa tarik lalu lepas, misalnyaACTION_DRAG_STARTED
,ACTION_DROP
, dll.ClipData
: Data sedang ditarik dan dienkapsulasi dalam objek ClipDataClipDescription
: Informasi meta tentang objek ClipDataResult
: Hasil operasi tarik lalu lepasX
: koordinat x dari lokasi objek yang ditarik saat iniY
: koordinat y dari lokasi objek yang ditarik saat ini
3. Penyiapan
Buat project baru dan pilih template "Empty Activity":
Biarkan semua parameter seperti default-nya.
Dalam codelab ini, kita akan menggunakan ImageView untuk mendemonstrasikan fungsi tarik lalu lepas. Mari tambahkan dependensi gradle library glide untuk menulis dan menyinkronkan project.
implementation("com.github.bumptech.glide:compose:1.0.0-beta01")
Sekarang di MainActivity.kt
, buat composable
untuk Gambar yang akan berfungsi sebagai sumber tarik untuk tujuan kita
@Composable
fun DragImage(url: String) {
GlideImage(model = url, contentDescription = "Dragged Image")
}
Buat juga gambar target Lepas.
@Composable
fun DropTargetImage(url: String) {
val urlState = remember {mutableStateOf(url)}
GlideImage(model = urlState.value, contentDescription = "Dropped Image")
}
Tambahkan composable kolom ke composable Anda untuk menyertakan dua gambar ini.
Column {
DragImage(url = getString(R.string.source_url))
DropTargetImage(url = getString(R.string.target_url))
}
Di tahap ini, kita memiliki MainActivity
yang menampilkan dua gambar secara vertikal. Anda akan dapat melihat layar ini.
4. Mengonfigurasi sumber Tarik
Mari tambahkan pengubah sumber Tarik lalu Lepas untuk composable DragImage kita
modifier = Modifier.dragAndDropSource {
detectTapGestures(
onLongPress = {
startTransfer(
DragAndDropTransferData(
ClipData.newPlainText("image uri", url)
)
)
}
)
}
Di sini, pengubah dragAndDropSource
telah ditambahkan. Pengubah dragAndDropSource
mengaktifkan fungsi tarik lalu lepas untuk setiap elemen yang diterapkan. Secara visual, elemen yang ditarik sebagai bayangan tarik mewakili elemen yang ditarik.
Pengubah dragAndDropSource
menyediakan PointerInputScope
untuk mendeteksi gestur tarik. Kita telah menggunakan detectTapGesture
PointerInputScope
untuk mendeteksi longPress yang merupakan gestur tarik.
Metode onLongPress
yang kita gunakan untuk memulai transfer data yang sedang ditarik.
startTransfer
memulai sesi tarik lalu lepas dengan transferData sebagai data yang akan ditransfer saat penyelesaian gestur. Diperlukan data yang dienkapsulasi di DragAndDropTransferData
yang memiliki 3 kolom
Clipdata:
data aktual yang akan ditransferflags
: tanda untuk mengontrol operasi tarik lalu lepaslocalState
: status lokal sesi saat menarik aktivitas yang sama
ClipData
adalah objek kompleks yang berisi item dari berbagai jenis seperti teks, markup, audio, video, dll. Untuk tujuan codelab ini, kita menggunakan imageurl sebagai item di ClipData.
Bagus, sekarang tampilan kita dapat ditarik.
5. Konfigurasi untuk Tarik
Agar dapat menerima item yang dilepas, tampilan harus menambahkan dragAndDropTarget
modifier
Modifier.dragAndDropTarget(
shouldStartDragAndDrop = {
// condition to accept dragged item
},
target = // DragAndDropTarget
)
)
dragAndDropTarget
adalah pengubah yang memungkinkan data ditarik dalam composable. Pengubah ini memiliki dua parameter
shouldStartDragAndDrop
: Mengizinkan Composable untuk memutuskan apakah ingin menerima dari sesi tarik lalu lepas tertentu dengan memeriksa DragAndDropEvent yang memulai sesi tersebut.target
: DragAndDropTarget yang akan menerima peristiwa untuk sesi tarik lalu lepas tertentu.
Mari tambahkan kondisi saat kita ingin meneruskan peristiwa tarik ke DragAndDropTarget
.
shouldStartDragAndDrop = { event ->
event.mimeTypes()
.contains(ClipDescription.MIMETYPE_TEXT_PLAIN)
}
Kondisi yang ditambahkan di sini hanya untuk mengizinkan tindakan lepas jika minimal salah satu item yang diseret adalah teks biasa. Target operasi lepas tidak akan diaktifkan jika tidak ada item yang berupa teks biasa.
Untuk parameter target, buat objek DragAndDropTarget
yang menangani sesi lepas.
val dndTarget = remember{
object : DragAndDropTarget{
// handle Drag event
}
}
DragAndDropTarget
memiliki callback yang harus diganti untuk setiap tahap dalam sesi tarik lalu lepas.
onDrop
: Item telah dilepas di dalam DragAndDropTarget ini, dan menampilkan nilai benar untuk menunjukkan bahwa DragAndDropEvent digunakan, sedangkan nilai salah menunjukkan bahwa item ditolakonStarted
: Sesi tarik lalu lepas baru saja dimulai dan DragAndDropTarget ini memenuhi syarat untuk menerimanya. Tindakan ini memberikan peluang untuk menetapkan status DragAndDropTarget sebagai persiapan untuk menggunakan sesi tarik lalu lepas.onEntered
: Item yang dihapus telah memasuki batas DragAndDropTarget ini.onMoved
: Item yang dihapus telah dipindahkan dalam batas DragAndDropTarget ini.onExited
: Item yang dihapus telah dipindahkan ke luar batas DragAndDropTarget ini.onChanged
: Peristiwa di sesi tarik lalu lepas saat ini telah berubah dalam batas DragAndDropTarget. Mungkin tombol pengubah telah ditekan atau dilepaskanonEnded
: Sesi tarik lalu lepas telah selesai. Semua instance DragAndDropTarget dalam hierarki yang sebelumnya menerima peristiwa onStarted akan menerima peristiwa ini. Tindakan ini memberikan peluang untuk mereset status DragAndDropTarget.
Mari tentukan apa yang terjadi saat item dilepas dalam composable target.
override fun onDrop(event: DragAndDropEvent): Boolean {
val draggedData = event.toAndroidDragEvent().clipData.getItemAt(0).text
urlState.value = draggedData.toString()
return true
}
Dalam fungsi onDrop
, kita mengekstrak item ClipData
dan menetapkannya ke URL gambar, serta menampilkan nilai benar untuk menunjukkan bahwa sesi tarik telah ditangani dengan benar.
Jangan izinkan plug menetapkan instance DragAndDropTarget
ini ke parameter target pengubah dragAndDropTarget
Modifier.dragAndDropTarget(
shouldStartDragAndDrop = { event ->
event.mimeTypes()
.contains(ClipDescription.MIMETYPE_TEXT_PLAIN)
},
target = dndTarget
)
Bagus, sekarang kita dapat melakukan operasi tarik lalu lepas.
Meskipun kita telah menambahkan fungsi tarik lalu lepas, sulit untuk memahami apa yang terjadi secara visual. Mari kita ubah.
Untuk melepaskan composable target, mari terapkan ColorFilter
ke gambar
var tintColor by remember {
mutableStateOf(Color(0xffE5E4E2))
}
Setelah menentukan warna tint, tambahkan ColorFilter
ke gambar
GlideImage(
colorFilter = ColorFilter.tint(color = backgroundColor,
blendMode = BlendMode.Modulate),
// other params
)
Kita ingin menerapkan tint ke warna ke gambar saat item yang ditarik memasuki area target Lepas. Untuk itu, kita dapat mengganti callback onEntered
override fun onEntered(event: DragAndDropEvent) {
super.onEntered(event)
tintColor = Color(0xff00ff00)
}
Selain itu, saat pengguna menarik keluar dari area target, kita harus melakukan penggantian ke filter warna asli. Untuk itu, kita harus mengganti callback onExited
override fun onExited(event: DragAndDropEvent) {
super.onEntered(event)
tintColor = Color(0xffE5E4E2)
}
Setelah berhasil menyelesaikan operasi tarik lalu lepas, kita juga dapat mengembalikan ke ColorFilter
asli
override fun onEnded(event: DragAndDropEvent) {
super.onEntered(event)
tintColor = Color(0xffE5E4E2)
}
Pada akhirnya, composable drop akan terlihat seperti ini
@Composable
fun DropTargetImage(url: String) {
val urlState = remember {
mutableStateOf(url)
}
var tintColor by remember {
mutableStateOf(Color(0xffE5E4E2))
}
val dndTarget = remember {
object : DragAndDropTarget {
override fun onDrop(event: DragAndDropEvent): Boolean {
val draggedData = event.toAndroidDragEvent()
.clipData.getItemAt(0).text
urlState.value = draggedData.toString()
return true
}
override fun onEntered(event: DragAndDropEvent) {
super.onEntered(event)
tintColor = Color(0xff00ff00)
}
override fun onEnded(event: DragAndDropEvent) {
super.onEntered(event)
tintColor = Color(0xffE5E4E2)
}
override fun onExited(event: DragAndDropEvent) {
super.onEntered(event)
tintColor = Color(0xffE5E4E2)
}
}
}
GlideImage(
model = urlState.value,
contentDescription = "Dropped Image",
colorFilter = ColorFilter.tint(color = tintColor,
blendMode = BlendMode.Modulate),
modifier = Modifier
.dragAndDropTarget(
shouldStartDragAndDrop = { event ->
event
.mimeTypes()
.contains(ClipDescription.MIMETYPE_TEXT_PLAIN)
},
target = dndTarget
)
)
}
Bagus, kita dapat menambahkan isyarat visual untuk operasi tarik lalu lepas.
6. Selamat!
Compose untuk Tarik lalu Lepas menyediakan antarmuka yang mudah untuk menerapkan fungsi tarik lalu lepas di Compose menggunakan pengubah untuk tampilan.
Di Ringkasan, Anda telah mempelajari cara menerapkan operasi tarik lalu lepas menggunakan compose. Pelajari dokumentasi lebih lanjut.
Pelajari lebih lanjut
- Mengaktifkan operasi tarik lalu lepas
- Contoh tarik lalu lepas
- Repositori contoh Codelab
- Membangun aplikasi untuk perangkat foldable
- Dukungan multi-aplikasi
- Tata letak responsif untuk pengembangan perangkat layar besar
- Jetpack WindowManager
- Contoh Jetpack WindowManager
- Mengembangkan aplikasi untuk perangkat dua layar