Menggambar UI hanyalah satu bagian dari membuat tampilan kustom. Anda juga perlu membuat tampilan Anda merespons input pengguna dengan cara yang sangat mirip dengan tindakan nyata yang Anda tiru.
Buat objek di aplikasi Anda bertindak seperti objek sungguhan. Misalnya, jangan biarkan gambar di aplikasi Anda muncul dan muncul kembali di tempat lain, karena objek di dunia nyata jangan lakukan itu. Sebagai gantinya, pindahkan gambar dari satu tempat ke lain.
Pengguna merasakan bahkan perilaku atau perasaan halus di antarmuka dan bereaksi paling baik terhadap halus yang meniru dunia nyata. Misalnya, saat pengguna melemparkan objek UI, memberi mereka rasa inersia di awal yang menunda gerakan. Di bagian akhir gerak, beri mereka momentum yang membawa objek melampaui ayunkan jari.
Halaman ini menunjukkan cara menggunakan fitur framework Android untuk menambahkan perilaku di dunia nyata ini pada tampilan kustom Anda.
Anda dapat menemukan informasi tambahan yang terkait di Ringkasan peristiwa input dan Animasi properti ringkasan.
Menangani gestur input
Seperti banyak framework UI lainnya, Android mendukung model peristiwa input. Pengguna
berubah menjadi peristiwa yang memicu callback, dan Anda bisa mengganti
callback untuk menyesuaikan cara aplikasi merespons pengguna. Input yang paling umum
di sistem Android adalah sentuh, yang memicu
onTouchEvent(android.view.MotionEvent)
.
Ganti metode ini untuk menangani peristiwa, sebagai berikut:
Kotlin
override fun onTouchEvent(event: MotionEvent): Boolean { return super.onTouchEvent(event) }
Java
@Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }
Peristiwa sentuh itu sendiri tidak terlalu berguna. UI sentuh modern
mendefinisikan interaksi dalam hal {i>gesture <i}seperti mengetuk, menarik, mendorong,
mengayunkan jari, dan melakukan zoom. Untuk mengonversi kejadian sentuh mentah menjadi gestur, Android
menyediakan
GestureDetector
.
Membuat GestureDetector
dengan meneruskan instance class
yang mengimplementasikan
GestureDetector.OnGestureListener
.
Jika Anda hanya ingin memproses
beberapa {i>gestures, <i} Anda dapat memperluas
GestureDetector.SimpleOnGestureListener
bukan menerapkan GestureDetector.OnGestureListener
dalam antarmuka berbasis web
yang sederhana. Misalnya, kode ini membuat class yang memperluas
GestureDetector.SimpleOnGestureListener
dan penggantian
onDown(MotionEvent)
.
Kotlin
private val myListener = object : GestureDetector.SimpleOnGestureListener() { override fun onDown(e: MotionEvent): Boolean { return true } } private val detector: GestureDetector = GestureDetector(context, myListener)
Java
class MyListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDown(MotionEvent e) { return true; } } detector = new GestureDetector(getContext(), new MyListener());
Baik Anda menggunakan GestureDetector.SimpleOnGestureListener
,
selalu menerapkan
onDown()
yang menampilkan true
. Hal ini diperlukan karena
semua {i>gesture <i}
diawali dengan pesan onDown()
. Jika Anda mengembalikan false
dari onDown()
, sebagai
GestureDetector.SimpleOnGestureListener
, sistem menganggap
Anda ingin mengabaikan sisa {i>gesture <i}tersebut, dan metode lainnya
GestureDetector.OnGestureListener
tidak dipanggil. Hanya pengembalian
false
dari onDown()
jika Anda ingin mengabaikan seluruh
{i>gesture <i}ini.
Setelah Anda menerapkan GestureDetector.OnGestureListener
dan membuat
instance GestureDetector
, Anda dapat menggunakan
GestureDetector
untuk menafsirkan peristiwa sentuh yang Anda terima di
onTouchEvent()
.
Kotlin
override fun onTouchEvent(event: MotionEvent): Boolean { return detector.onTouchEvent(event).let { result -> if (!result) { if (event.action == MotionEvent.ACTION_UP) { stopScrolling() true } else false } else true } }
Java
@Override public boolean onTouchEvent(MotionEvent event) { boolean result = detector.onTouchEvent(event); if (!result) { if (event.getAction() == MotionEvent.ACTION_UP) { stopScrolling(); result = true; } } return result; }
Saat Anda meneruskan peristiwa sentuh ke onTouchEvent()
yang tidak dilakukan
kenali sebagai bagian dari gestur, fungsi ini akan menampilkan false
. Anda kemudian dapat menjalankan
kode deteksi gestur khusus Anda sendiri.
Membuat gerakan yang masuk akal secara fisik
{i>Gesture <i}adalah cara yang ampuh untuk mengontrol perangkat layar sentuh, tetapi mereka kontra-intuitif dan sulit diingat kecuali mereka menghasilkan secara fisik hasil yang masuk akal.
Misalnya, Anda ingin mengimplementasikan gestur ayunkan jari horizontal yang menyetel item yang digambar dalam tampilan yang berputar di sekitar sumbu vertikalnya. Gestur ini masuk akal jika UI merespons dengan bergerak cepat ke arah ayunan, kemudian melambat, seolah-olah pengguna mendorong roda gila dan memutarnya.
Dokumentasi tentang cara
menganimasikan scroll
gestur memberikan penjelasan mendetail tentang cara menerapkan scoll Anda sendiri
perilaku model. Namun, menyimulasikan nuansa roda inovasi bukanlah hal yang sepele. Banyak langkah fisika
dan matematika diperlukan untuk membuat
model roda inovasi bekerja dengan benar. Untungnya,
Android menyediakan class helper untuk menyimulasikan hal ini dan perilaku lainnya. Tujuan
Scroller
adalah dasar untuk menangani gestur ayunkan jari gaya roda inovasi.
Untuk mulai melempar, panggil
fling()
dengan kecepatan awal serta nilai minimum dan maksimum x dan y
fling-nya. Untuk nilai kecepatan, Anda dapat
menggunakan nilai yang dihitung dengan
GestureDetector
.
Kotlin
fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean { scroller.fling( currentX, currentY, (velocityX / SCALE).toInt(), (velocityY / SCALE).toInt(), minX, minY, maxX, maxY ) postInvalidate() return true }
Java
@Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { scroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY); postInvalidate(); return true; }
Panggilan ke fling()
akan menyiapkan model fisika untuk fling tersebut
{i>gesture <i}ini. Setelah itu, update Scroller
dengan memanggil
Scroller.computeScrollOffset()
dengan interval yang teratur. computeScrollOffset()
memperbarui
status internal objek Scroller
dengan membaca waktu saat ini dan
menggunakan model fisika untuk menghitung posisi x dan y pada
baik. Telepon
getCurrX()
dan
getCurrY()
untuk mengambil nilai-nilai ini.
Sebagian besar tampilan meneruskan x dan y objek Scroller
posisi langsung ke
scrollTo()
.
Contoh ini sedikit berbeda: ini menggunakan posisi scroll x saat ini
untuk menyetel sudut rotasi tampilan.
Kotlin
scroller.apply { if (!isFinished) { computeScrollOffset() setItemRotation(currX) } }
Java
if (!scroller.isFinished()) { scroller.computeScrollOffset(); setItemRotation(scroller.getCurrX()); }
Class Scroller
menghitung posisi scroll untuk Anda, tetapi
tidak menerapkan posisi tersebut secara otomatis ke tampilan Anda. Terapkan koordinat baru
cukup sering untuk membuat animasi {i>scrolling<i} terlihat mulus. Ada dua cara untuk
lakukan ini:
- Paksa gambar ulang dengan memanggil
postInvalidate()
setelah memanggilfling()
. Teknik ini mengharuskan Anda offset scroll dalamonDraw()
dan memanggilpostInvalidate()
setiap kali offset scroll perubahan. - Siapkan
ValueAnimator
untuk menganimasikan durasi fling dan menambahkan pemroses untuk memproses pembaruan animasi dengan memanggiladdUpdateListener()
. Teknik ini memungkinkan Anda menganimasikan propertiView
.
Buat transisi Anda lancar
Pengguna mengharapkan UI modern untuk bertransisi dengan lancar antar-status: elemen UI menjadi jelas dan memudar, bukannya muncul dan menghilang, dan gerakan dimulai dan berakhir dengan lancar alih-alih memulai dan berhenti tiba-tiba. Android animasi properti membuat transisi yang lancar menjadi lebih mudah.
Untuk menggunakan sistem animasi, setiap kali properti mengubah hal yang memengaruhi
tampilan tampilan, jangan mengubah properti secara langsung. Sebagai gantinya, gunakan
ValueAnimator
untuk melakukan perubahan. Dalam contoh berikut,
memodifikasi komponen turunan yang dipilih dalam tampilan akan membuat seluruh proses
diputar sehingga pointer pemilihan berada di tengah.
ValueAnimator
mengubah rotasi dalam jangka waktu beberapa ratus
milidetik, bukan langsung menetapkan nilai rotasi baru.
Kotlin
autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0).apply { setIntValues(targetAngle) duration = AUTOCENTER_ANIM_DURATION start() }
Java
autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0); autoCenterAnimator.setIntValues(targetAngle); autoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION); autoCenterAnimator.start();
Jika nilai yang ingin Anda ubah adalah salah satu dari View
dasar
properti, membuat animasi jauh lebih mudah, karena tampilan memiliki
ViewPropertyAnimator
yang dioptimalkan untuk animasi simultan beberapa properti, seperti pada
contoh berikut:
Kotlin
animate() .rotation(targetAngle) .duration = ANIM_DURATION .start()
Java
animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();