Tempat terbaik untuk menghilangkan mitos ini adalah kode sumber. Dokumen itu sangat tidak memadai untuk menjelaskan hal ini.
dispatchTouchEvent sebenarnya didefinisikan pada Activity, View, dan ViewGroup. Anggap saja sebagai pengontrol yang memutuskan cara mengarahkan acara sentuh.
Misalnya, kasus paling sederhana adalah pada View.dispatchTouchEvent yang akan merutekan acara sentuh ke OnTouchListener.onTouch jika ditentukan atau ke metode ekstensi onTouchEvent .
Untuk ViewGroup.dispatchTouchEvent, berbagai hal jauh lebih rumit. Perlu mengetahui yang mana dari salah satu pandangan anaknya yang harus mendapatkan acara (dengan memanggil child.dispatchTouchEvent). Ini pada dasarnya adalah algoritma pengujian hit di mana Anda mengetahui persegi panjang pembatas tampilan anak mana yang berisi koordinat titik sentuh.
Tetapi sebelum dapat mengirimkan acara ke tampilan anak yang sesuai, orang tua dapat memata-matai dan / atau mencegat acara tersebut bersama-sama. Inilah yang ada di dalamInterceptTouchEvent . Jadi ia memanggil metode ini terlebih dahulu sebelum melakukan pengujian hit dan jika acara tersebut dibajak (dengan mengembalikan true dari onInterceptTouchEvent) mengirimkan ACTION_CANCEL ke tampilan anak sehingga mereka dapat meninggalkan pemrosesan acara sentuh mereka (dari acara sentuh sebelumnya) dan sejak saat itu dan seterusnya semua acara sentuh di tingkat induk dikirim ke onTouchListener.onTouch (jika ditentukan) atau onTouchEvent (). Juga dalam kasus itu, onInterceptTouchEvent tidak pernah dipanggil lagi.
Apakah Anda bahkan ingin menimpa [Activity | ViewGroup | View] .dispatchTouchEvent? Kecuali Anda melakukan perutean kustom, Anda mungkin tidak seharusnya.
Metode ekstensi utama adalah ViewGroup.onInterceptTouchEvent jika Anda ingin memata-matai dan / atau mencegat acara sentuh di tingkat induk dan View.onTouchListener / View.onTouchEvent untuk penanganan acara utama.
Semua dalam semua desain imo yang terlalu rumit tetapi apis android lebih condong ke arah fleksibilitas daripada kesederhanaan.
Karena ini adalah hasil pertama di Google. Saya ingin berbagi dengan Anda Talk yang hebat oleh Dave Smith di Youtube: Menguasai Sistem Android Touch dan slide tersedia di sini . Ini memberi saya pemahaman mendalam tentang Sistem Sentuh Android:
Cara Aktivitas menangani sentuhan:
Bagaimana View menangani sentuhan:
Cara ViewGroup menangani sentuhan:
Dia juga memberikan contoh kode sentuhan khusus pada github.com/devunwired/ .
Jawaban: Pada dasarnya
dispatchTouchEvent()
ini dipanggil pada setiapView
layer untuk menentukan apakah aView
tertarik pada gerakan yang sedang berlangsung. DalamViewGroup
satuViewGroup
memiliki kemampuan untuk mencuri peristiwa sentuhan dalam bukunyadispatchTouchEvent()
-metode, sebelum itu akan memanggildispatchTouchEvent()
pada anak-anak. HanyaViewGroup
akan menghentikan pengiriman jikaViewGroup
onInterceptTouchEvent()
-metode mengembalikan true. The perbedaan adalah bahwadispatchTouchEvent()
akan mengirimMotionEvents
danonInterceptTouchEvent
mengatakan jika itu harus mencegat (tidak pengiriman yangMotionEvent
untuk anak-anak) atau tidak (pengiriman kepada anak-anak) .Anda dapat membayangkan kode dari suatu ViewGroup melakukan lebih atau kurang ini (sangat disederhanakan):
sumber
Jawaban Tambahan
Berikut adalah beberapa suplemen visual untuk jawaban lainnya. Jawaban lengkap saya ada di sini .
The
dispatchTouchEvent()
Metode dariViewGroup
penggunaanonInterceptTouchEvent()
untuk memilih apakah harus segera menangani event sentuhan (denganonTouchEvent()
) atau terus memberitahudispatchTouchEvent()
metode anak-anaknya.sumber
Ada banyak kebingungan tentang metode ini, tetapi sebenarnya tidak terlalu rumit. Sebagian besar kebingungan adalah karena:
View/ViewGroup
atau salah satu anaknya tidak kembali benaronTouchEvent
,dispatchTouchEvent
danonInterceptTouchEvent
HANYA akan dipanggil untukMotionEvent.ACTION_DOWN
. Tanpa true fromonTouchEvent
, tampilan induk akan menganggap tampilan Anda tidak memerlukan MotionEvents.MotionEvent.ACTION_DOWN
, bahkan jika ViewGroup Anda mengembalikan true dalamonTouchEvent
.Pesanan pemrosesan seperti ini:
dispatchTouchEvent
disebut.onInterceptTouchEvent
dipanggil untukMotionEvent.ACTION_DOWN
atau ketika salah satu anak-anak di ViewGroup mengembalikan true inonTouchEvent
.onTouchEvent
pertama kali dipanggil pada anak-anak di ViewGroup dan ketika tidak ada anak yang mengembalikan true itu dipanggil padaView/ViewGroup
.Jika Anda ingin melihat pratinjau
TouchEvents/MotionEvents
tanpa menonaktifkan acara pada anak-anak Anda, Anda harus melakukan dua hal:dispatchTouchEvent
untuk melihat acara dan kembalisuper.dispatchTouchEvent(ev)
;onTouchEvent
dan kembalikan benar, jika tidak, Anda tidak akan mendapatkannyaMotionEvent
kecualiMotionEvent.ACTION_DOWN
.Jika Anda ingin mendeteksi beberapa gerakan seperti acara gesek, tanpa menonaktifkan acara lain pada anak-anak Anda selama Anda tidak mendeteksi gerakan tersebut, Anda dapat melakukannya seperti ini:
onInterceptTouchEvent
ketika bendera Anda diatur untuk membatalkan pemrosesan MotionEvent oleh anak-anak Anda. Ini juga tempat yang nyaman untuk mengatur ulang flag Anda, karena onInterceptTouchEvent tidak akan dipanggil lagi sampai yang berikutnyaMotionEvent.ACTION_DOWN
.Contoh override dalam
FrameLayout
(contoh saya adalah C # saat saya pemrograman dengan Xamarin Android, tetapi logikanya sama di Jawa):sumber
Saya mendapat penjelasan yang sangat intuitif di laman web ini http://doandroids.com/blogs/tag/codeexample/ . Diambil dari sana:
sumber
menangani dispatchTouchEvent sebelum diInterceptTouchEvent.
Menggunakan contoh sederhana ini:
Anda dapat melihat bahwa log akan seperti:
Jadi jika Anda bekerja dengan 2 penangan ini gunakan dispatchTouchEvent untuk menangani acara instance pertama, yang akan pergi ke onInterceptTouchEvent.
Perbedaan lainnya adalah bahwa jika dispatchTouchEvent mengembalikan 'false', acara tersebut tidak dapat disebarkan ke anak, dalam hal ini EditText, sedangkan jika Anda mengembalikan false ke dalamInterceptTouchEvent acara masih dapat dikirim ke EditText
sumber
Jawaban singkat:
dispatchTouchEvent()
akan dipanggil pertama -tama.Saran singkat: jangan ditimpa
dispatchTouchEvent()
karena sulit dikendalikan, kadang-kadang dapat memperlambat kinerja Anda. IMHO, saya sarankan menggantionInterceptTouchEvent()
.Karena sebagian besar jawaban menyebutkan dengan cukup jelas tentang peristiwa aliran sentuh pada aktivitas / grup tampilan / tampilan, saya hanya menambahkan lebih detail tentang kode pada metode ini di
ViewGroup
(mengabaikandispatchTouchEvent()
):onInterceptTouchEvent()
akan dipanggil pertama, AKSI akan dipanggil masing-masing turun -> pindah -> naik. Ada 2 kasus:Jika Anda mengembalikan false dalam 3 kasus (ACTION_DOWN, ACTION_MOVE, ACTION_UP), itu akan dipertimbangkan karena orang tua tidak akan memerlukan acara sentuh ini , jadi
onTouch()
orang tua tidak pernah menelepon , tetapionTouch()
anak-anak akan memanggil sebaliknya ; namun harap perhatikan:onInterceptTouchEvent()
masih terus menerima acara sentuhan, selama anak-anaknya tidak meneleponrequestDisallowInterceptTouchEvent(true)
.onTouch()
orang tua.Begitu juga sebaliknya, jika Anda mengembalikan true , orang tua akan segera mencuri acara sentuhan ini , dan
onInterceptTouchEvent()
akan segera berhenti, alihonTouch()
- alih orang tua akan dipanggil dan semuaonTouch()
anak akan menerima acara tindakan terakhir - ACTION_CANCEL (dengan demikian, itu berarti orang tua mencuri acara sentuhan, dan anak-anak tidak bisa mengatasinya sejak saat itu). AliranonInterceptTouchEvent()
return false adalah normal, tetapi ada sedikit kebingungan dengan return true case, jadi saya daftar di sini:onTouch()
dari orang tua akan menerima ACTION_DOWN lagi dan mengikuti tindakan (ACTION_MOVE, ACTION_UP).onTouch()
dari orang tua akan menerima ACTION_MOVE berikutnya (bukan ACTION_MOVE yang samaonInterceptTouchEvent()
) dan tindakan berikut (ACTION_MOVE, ACTION_UP).onTouch()
orang tua TIDAK akan menelepon sama sekali karena sudah terlambat bagi orang tua untuk mencuri acara sentuhan.Satu hal lagi yang penting adalah ACTION_DOWN dari acara di
onTouch()
akan menentukan apakah tampilan ingin menerima lebih banyak tindakan dari acara itu atau tidak. Jika tampilan mengembalikan true di ACTION_DOWN dalamonTouch()
, itu berarti tampilan bersedia menerima lebih banyak tindakan dari peristiwa itu. Jika tidak, kembalikan salah pada ACTION_DOWN dionTouch()
akan menyiratkan bahwa tampilan tidak akan menerima tindakan lagi dari peristiwa itu.sumber
Anda dapat menemukan jawabannya di video ini https://www.youtube.com/watch?v=SYoN-OvdZ3M&list=PLonJJ3BVjZW6CtAMbJz1XD8ELUs1KXaTD&index=19 dan 3 video berikutnya. Semua acara sentuh dijelaskan dengan sangat baik, sangat jelas dan penuh dengan contoh.
sumber
Kode berikut dalam subkelas ViewGroup akan mencegah wadah induknya menerima acara sentuh:
Saya menggunakan ini dengan overlay khusus untuk mencegah tampilan latar belakang merespons acara sentuh.
sumber
Perbedaan utama :
sumber
ViewGroup
onInterceptTouchEvent()
selalu menjadi titik masuk untukACTION_DOWN
acara yang merupakan acara pertama yang terjadi.Jika Anda ingin ViewGroup memproses gerakan ini, kembalikan benar dari
onInterceptTouchEvent()
. Pada kembali benar, ViewGroup inionTouchEvent()
akan menerima semua kejadian setelah sampai berikutnyaACTION_UP
atauACTION_CANCEL
, dan dalam kebanyakan kasus, peristiwa sentuhan antaraACTION_DOWN
danACTION_UP
atauACTION_CANCEL
yangACTION_MOVE
, yang biasanya akan diakui sebagai bergulir / melemparkan isyarat.Jika Anda mengembalikan false dari
onInterceptTouchEvent()
, tampilan targetonTouchEvent()
akan dipanggil. Ini akan diulangi untuk pesan selanjutnya sampai Anda mengembalikan true darionInterceptTouchEvent()
.Sumber: http://neevek.net/posts/2013/10/13/implementing-onInterceptTouchEvent-and-onTouchEvent-for-ViewGroup.html
sumber
Baik Activity dan View memiliki metode dispatchTouchEvent () dan onTouchEvent. ViewGroup juga memiliki metode ini, tetapi memiliki metode lain yang disebut onInceptceptTouchEvent. Jenis pengembalian dari metode tersebut adalah boolean, Anda dapat mengontrol rute pengiriman melalui nilai kembali.
Pengiriman acara di Android dimulai dari Activity-> ViewGroup-> View.
sumber
sumber
Jawaban kecil:
onInterceptTouchEvent datang sebelum setOnTouchListener.
sumber