Konsep utama

Mencoba cara Compose
Jetpack Compose adalah toolkit UI yang direkomendasikan untuk Android. Pelajari cara menggunakan operasi tarik lalu lepas di Compose.

Bagian berikut menjelaskan beberapa konsep utama untuk proses tarik lalu lepas.

Proses tarik lalu lepas

Ada empat langkah atau status dalam proses tarik lalu lepas: dimulai, dilanjutkan, dilepas, dan diakhiri.

Dimulai

Sebagai respons terhadap gestur tarik pengguna, aplikasi Anda memanggil startDragAndDrop() untuk memberi tahu sistem agar memulai operasi tarik lalu lepas. Argumen metode ini memberikan hal berikut:

  • Data yang akan ditarik.
  • Callback untuk menggambar bayangan tarik
  • Metadata yang menjelaskan data yang ditarik
  • Sistem akan merespons dengan melakukan callback ke aplikasi Anda untuk mendapatkan bayangan tarik. Sistem kemudian menampilkan bayangan tarik di perangkat.
  • Selanjutnya, sistem mengirimkan peristiwa tarik dengan jenis tindakan ACTION_DRAG_STARTED ke pemroses peristiwa tarik untuk semua View objek dalam tata letak saat ini. Untuk terus menerima peristiwa tarik, termasuk kemungkinan peristiwa lepas, pemroses peristiwa tarik harus menampilkan true. Tindakan ini akan mendaftarkan pemroses ke sistem. Hanya pemroses terdaftar yang terus menerima peristiwa tarik. Pada tahap ini, pemroses juga dapat mengubah tampilan objek View target lepas untuk menunjukkan bahwa tampilan dapat menerima peristiwa lepas.
  • Jika pemroses peristiwa tarik menampilkan false, pemroses tidak akan menerima peristiwa tarik untuk operasi saat ini hingga sistem mengirimkan peristiwa tarik dengan jenis tindakan ACTION_DRAG_ENDED. Dengan menampilkan false, pemroses memberi tahu sistem bahwa pemroses tidak tertarik dengan operasi tarik lalu lepas dan tidak ingin menerima data yang ditarik.
Melanjutkan
Pengguna melanjutkan operasi tarik. Saat bayangan tarik memotong kotak pembatas dari target lepas, sistem akan mengirimkan satu atau beberapa peristiwa tarik ke pemroses peristiwa tarik target. Pemroses dapat mengubah tampilan View target lepas sebagai respons terhadap peristiwa tersebut. Misalnya, jika peristiwa itu menunjukkan bahwa bayangan tarik memasuki kotak pembatas target lepas—jenis tindakan ACTION_DRAG_ENTERED —pemroses dapat bereaksi dengan menyorot View.
Dilepas
Pengguna merilis bayangan tarik di dalam kotak pembatas target lepas. Sistem mengirimkan peristiwa tarik ke pemroses target lepas dengan jenis tindakan ACTION_DROP. Objek peristiwa tarik berisi data yang diteruskan ke sistem dalam panggilan ke startDragAndDrop() yang memulai operasi. Pemroses diharapkan menampilkan boolean true ke sistem jika pemroses berhasil memproses data yang dilepas. : Langkah ini hanya terjadi jika pengguna melepas bayangan tarik di dalam kotak pembatas View yang pemrosesnya terdaftar untuk menerima peristiwa tarik (target operasi lepas). Jika pengguna merilis bayangan tarik dalam situasi lain, tidak ada peristiwa tarik ACTION_DROP yang dikirim.
Diakhiri

Setelah pengguna merilis bayangan tarik, dan setelah sistem mengirim

peristiwa tarik dengan jenis tindakan ACTION_DROP, jika perlu, sistem akan mengirimkan peristiwa tarik dengan jenis tindakan ACTION_DRAG_ENDED untuk menunjukkan bahwa operasi tarik lalu lepas telah selesai. Hal ini dilakukan di mana pun pengguna merilis bayangan tarik. Peristiwa ini dikirim ke setiap pemroses yang terdaftar untuk menerima peristiwa tarik, meskipun pemroses juga menerima peristiwa ACTION_DROP.

Setiap langkah ini dijelaskan lebih mendetail di bagian yang disebut Operasi tarik lalu lepas.

Peristiwa tarik

Sistem mengirimkan peristiwa tarik dalam bentuk objek DragEvent, yang berisi jenis tindakan yang menjelaskan apa yang terjadi dalam proses tarik lalu lepas. Tergantung pada jenis tindakan, objek juga dapat berisi data lain.

Pemroses peristiwa tarik menerima objek DragEvent. Untuk mendapatkan jenis tindakan, pemroses memanggil DragEvent.getAction(). Ada enam kemungkinan nilai yang ditentukan oleh konstanta dalam class DragEvent, yang dijelaskan dalam tabel 1:

Tabel 1. Jenis tindakan DragEvent

Jenis tindakan Arti
ACTION_DRAG_STARTED Aplikasi memanggil startDragAndDrop() dan mendapatkan bayangan tarik. Jika pemroses ingin terus menerima peristiwa tarik untuk operasi ini, pemroses harus menampilkan boolean true ke sistem.
ACTION_DRAG_ENTERED Bayangan tarik memasuki kotak pembatas pemroses peristiwa tarik View. Ini adalah jenis tindakan peristiwa pertama yang diterima pemroses saat bayangan tarik memasuki kotak pembatas.
ACTION_DRAG_LOCATION Setelah peristiwa ACTION_DRAG_ENTERED bayangan tarik masih berada dalam kotak pembatas pemroses peristiwa tarik View.
ACTION_DRAG_EXITED Setelah ACTION_DRAG_ENTERED dan setidaknya satu ACTION_DRAG_LOCATION peristiwa, bayangan tarik bergerak ke luar kotak pembatas View pemroses peristiwa tarik.
ACTION_DROP Bayangan tarik dilepas melalui pemroses peristiwa tarik's View. Jenis tindakan ini dikirim ke objek View pemroses hanya jika pemroses menampilkan boolean true sebagai respons terhadap ACTION_DRAG_STARTED peristiwa tarik. Jenis tindakan ini tidak dikirim jika pengguna merilis bayangan tarik di atas View yang pemrosesnya tidak terdaftar, atau jika pengguna merilis bayangan tarik di atas apa pun yang bukan bagian dari tata letak saat ini.

Pemroses menampilkan boolean true jika berhasil memproses operasi lepas. Jika tidak, pemroses harus menampilkan false.

ACTION_DRAG_ENDED Sistem mengakhiri operasi tarik lalu lepas. Jenis tindakan ini tidak perlu didahului oleh peristiwa ACTION_DROP. Jika sistem mengirim ACTION_DROP, penerimaan jenis tindakan ACTION_DRAG_ENDED bukan berarti bahwa operasi lepas berhasil. Pemroses harus memanggil getResult(), seperti yang ditunjukkan dalam tabel 2, untuk mendapatkan nilai yang ditampilkan sebagai respons terhadap ACTION_DROP. Jika peristiwa ACTION_DROP tidak dikirim, maka getResult() menampilkan false.

Objek DragEvent juga berisi data dan metadata yang disediakan aplikasi Anda ke sistem dalam panggilan ke startDragAndDrop(). Sebagian data hanya valid untuk jenis tindakan tertentu seperti yang diringkas dalam tabel 2. Untuk mengetahui informasi selengkapnya tentang peristiwa dan data terkaitnya, lihat bagian yang disebut Operasi tarik lalu lepas.

Tabel 2. Data DragEvent yang valid menurut jenis tindakan

getAction()
nilai
getClipDescription()
nilai
getLocalState()
nilai
getX()
nilai
getY()
nilai
getClipData()
nilai
getResult()
nilai
ACTION_DRAG_STARTED &periksa; &periksa;        
ACTION_DRAG_ENTERED &periksa; &periksa;        
ACTION_DRAG_LOCATION &periksa; &periksa; &periksa; &periksa;    
ACTION_DRAG_EXITED &periksa; &periksa;        
ACTION_DROP &periksa; &periksa; &periksa; &periksa; &periksa;  
ACTION_DRAG_ENDED   &periksa;       &periksa;

Metode DragEvent getAction(), describeContents(), writeToParcel(), dan toString() selalu menampilkan data yang valid.

Jika sebuah metode tidak berisi data yang valid untuk jenis tindakan tertentu, metode tersebut akan menampilkan null atau 0, bergantung pada jenis hasilnya.

Bayangan tarik

Selama operasi tarik lalu lepas, sistem menampilkan gambar yang ditarik pengguna. Untuk pemindahan data, gambar ini mewakili data yang sedang ditarik. Untuk operasi lainnya, gambar ini mewakili beberapa aspek operasi tarik.

Gambar ini disebut bayangan tarik. Anda membuatnya dengan metode yang Anda deklarasikan untuk objek View.DragShadowBuilder. Anda meneruskan builder ke sistem saat memulai operasi tarik lalu lepas menggunakan startDragAndDrop(). Sebagai bagian dari respons terhadap startDragAndDrop(), sistem memanggil metode callback yang Anda tentukan di View.DragShadowBuilder untuk mendapatkan bayangan tarik.

Class View.DragShadowBuilder memiliki dua konstruktor:

View.DragShadowBuilder(View)

Konstruktor ini menerima objek View apa pun dari aplikasi Anda. Konstruktor menyimpan objek View dalam objek View.DragShadowBuilder, sehingga callback dapat mengaksesnya untuk mengonstruksi bayangan tarik. Tampilan tidak harus berupa View yang dipilih pengguna untuk memulai operasi tarik.

Jika menggunakan konstruktor ini, Anda tidak perlu memperluas View.DragShadowBuilder atau mengganti metodenya. Secara default, Anda akan mendapatkan bayangan tarik yang tampilannya sama dengan View yang Anda teruskan sebagai argumen, yang berpusat di bawah lokasi tempat pengguna menyentuh layar.

View.DragShadowBuilder()

Jika Anda menggunakan konstruktor ini, tidak ada View objek yang tersedia dalam objek View.DragShadowBuilder. Kolom ini ditetapkan ke null. Anda harus memperluas View.DragShadowBuilder dan mengganti metodenya, atau Anda akan mendapatkan bayangan tarik yang tidak terlihat. Sistem tidak akan menampilkan error.

Class View.DragShadowBuilder memiliki dua metode yang bersama-sama membuat bayangan tarik:

onProvideShadowMetrics()

Sistem akan memanggil metode ini segera setelah Anda memanggil startDragAndDrop(). Gunakan metode ini untuk mengirim dimensi dan titik sentuh bayangan tarik ke sistem. Metode ini memiliki dua parameter:

outShadowSize: objek Point. Lebar bayangan tarik masuk di x, dan tingginya masuk di y.

outShadowTouchPoint: objek Point. Titik sentuh adalah lokasi dalam bayangan tarik yang harus berada di bawah jari pengguna selama operasi tarik. Posisi X masuk di x dan posisi Y masuk di y.

onDrawShadow()

Segera setelah panggilan ke onProvideShadowMetrics(), sistem akan memanggil onDrawShadow() untuk membuat bayangan tarik. Metode ini memiliki satu argumen, objek Canvas yang dibuat sistem dari parameter yang Anda berikan di onProvideShadowMetrics(). Metode ini menggambar bayangan tarik pada Canvas yang disediakan.

Untuk meningkatkan performa, sebaiknya ukuran bayangan tarik dibuat sekecil mungkin. Untuk satu item, sebaiknya gunakan ikon. Untuk pilihan beberapa item, sebaiknya gunakan ikon dalam tumpukan, bukan gambar lengkap yang tersebar di layar.

Pemroses peristiwa tarik dan metode callback

A View menerima peristiwa tarik dengan pemroses peristiwa tarik yang mengimplementasikan View.OnDragListener atau dengan metode callback onDragEvent() tampilan. Saat memanggil metode atau pemroses, sistem akan memberikan argumen DragEvent.

Umumnya, saat menggunakan pemroses lebih baik menggunakan metode callback. Saat mendesain UI, biasanya Anda tidak membuat subclass untuk class View, tetapi menggunakan metode callback akan memaksa Anda membuat subclass untuk mengganti metode. Sebagai perbandingan, Anda dapat mengimplementasikan satu class pemroses lalu menggunakannya dengan beberapa objek View yang berbeda. Anda juga dapat mengimplementasikannya sebagai class inline anonim atau ekspresi lambda. Untuk menetapkan pemroses untuk objek View, panggil setOnDragListener().

Sebagai alternatif, Anda dapat mengubah implementasi default onDragEvent() tanpa mengganti metode. Tetapkan OnReceiveContentListener pada tampilan; untuk mengetahui detail selengkapnya, lihat setOnReceiveContentListener(). Metode onDragEvent() kemudian melakukan hal berikut secara default:

  • Menampilkan nilai benar sebagai respons terhadap panggilan ke startDragAndDrop().
  • Memanggil performReceiveContent() jika data tarik lalu lepas dilepas pada tampilan. Data diteruskan ke metode sebagai ContentInfo objek. Metode ini memanggil OnReceiveContentListener.

  • Menampilkan nilai benar jika data tarik lalu lepas dilepas pada tampilan dan OnReceiveContentListener menggunakan salah satu konten.

Tentukan OnReceiveContentListener yang akan menangani data khusus untuk aplikasi Anda. Untuk kompatibilitas mundur hingga API level 24, gunakan versi Jetpack OnReceiveContentListener.

Anda dapat menggunakan pemroses peristiwa tarik dan metode callback untuk objek View yang dalam hal ini sistem akan memanggil pemroses terlebih dahulu. Sistem tidak memanggil metode callback kecuali jika pemroses menampilkan false.

Gabungan dari metode onDragEvent() dan View.OnDragListener serupa dengan gabungan dari onTouchEvent() dan View.OnTouchListener yang digunakan dengan peristiwa sentuh.