2011-09-16 27 views
17

Tôi không hỏi làm thế nào để xử lý các sự kiện liên lạc, nhưng những gì đang xảy ra đằng sau hậu trường? Nếu có một số tiện ích con lồng nhau, thứ tự nào họ thấy các sự kiện trong đó? Nhà phát triển có bất kỳ quyền kiểm soát nào không? Lý tưởng nhất là tôi muốn một tài liệu về chủ đề này.Sự kiện chạm trên Android được phân phối như thế nào?

Trả lời

21

Từ quan điểm hoạt động:

Sự kiện cảm ứng được gửi trước đến Activity.dispatchTouchEvent. Đó là nơi bạn có thể bắt chúng trước. Ở đây họ được gửi đến Window, nơi họ đi qua hệ thống phân cấp Xem, theo thứ tự mà các Widget được vẽ cuối cùng (trên đầu các tiện ích khác) có cơ hội xử lý liên lạc trong View.onTouchEvent trước tiên. Nếu một số Chế độ xem trả về true trong onTouchEvent, thì dừng truyền tải và các Chế độ xem khác sẽ không nhận được sự kiện chạm.

Cuối cùng, nếu không Chế độ xem nào tiêu thụ liên lạc, nó sẽ được gửi đến Activity.onTouchEvent.

Đó là tất cả sự kiểm soát của bạn. Và hợp lý là những gì bạn thấy được vẽ lên trên một thứ gì đó khác, có cơ hội để xử lý sự kiện cảm ứng trước khi một cái gì đó được vẽ bên dưới nó.

+0

Bạn có bất kỳ loại tài liệu mô tả này? – DJClayworth

+0

Giới thiệu về điều phối: Tôi có thể đọc các nhận xét về mã nguồn và chức năng. Giới thiệu về trật tự xem Traversal - Tôi đã đọc nó trong một số tài liệu, chắc chắn trên developer.android.com, nhưng không thể nói chính xác cái nào. –

+0

Dù sao, bắt đầu tốt: http://developer.android.com/guide/topics/ui/ui-events.html –

10

Hãy xem ví dụ trực quan.

enter image description here

Khi một sự kiện liên lạc xảy ra, tất cả mọi người đầu tiên được thông báo về sự kiện này, bắt đầu từ các hoạt động và đi tất cả các cách để quan điểm trên. Sau đó, mọi người đều có cơ hội để xử lý sự kiện, bắt đầu với chế độ xem ở trên cùng và quay trở lại Hoạt động. Vì vậy, Activity là người đầu tiên nghe về nó và người cuối cùng được trao cơ hội để xử lý nó.

enter image description here

Nếu Hoạt động hoặc một số ViewGroup muốn để xử lý các sự kiện liên lạc ngay lập tức (và không cho bất cứ ai khác xuống dòng một cơ hội vào nó) sau đó nó chỉ có thể trở lại true trong onInterceptTouchEvent() của nó.

Nếu Chế độ xem (hoặc Nhóm xem) có OnTouchListener thì sự kiện chạm được xử lý bởi OnTouchListener.onTouch(). Nếu không, nó sẽ được xử lý bởi onTouchEvent(). Nếu onTouchEvent() trả về true cho bất kỳ sự kiện chạm nào, thì việc xử lý dừng lại ở đó. Không ai khác xuống dòng được một cơ hội ở đó.

Giải thích chi tiết hơn

Biểu đồ trên làm cho mọi thứ đơn giản hơn một chút so với thực tế. Ví dụ, giữa Activity và ViewGroup A (layout gốc) cũng có Window và DecorView. Tôi để chúng ở trên vì chúng ta thường không phải tương tác với chúng. Tuy nhiên, tôi sẽ bao gồm chúng bên dưới. Mô tả bên dưới tuân theo sự kiện chạm thông qua mã nguồn. Bạn có thể nhấp vào liên kết để xem mã nguồn thực tế.

  1. Hoạt động của dispatchTouchEvent() được thông báo về sự kiện liên lạc. Sự kiện cảm ứng được chuyển vào dưới dạng MotionEvent, chứa tọa độ x, y, thời gian, loại sự kiện và thông tin khác.
  2. Sự kiện cảm ứng được gửi đến cửa sổ superDispatchTouchEvent() của Cửa sổ. Window là một lớp trừu tượng. Việc triển khai thực tế là PhoneWindow.
  3. Dòng tiếp theo trong dòng để nhận thông báo là số superDispatchTouchEvent() của DecorView.DecorView là cách xử lý thanh trạng thái, thanh điều hướng, khu vực nội dung, v.v. It is actually just a FrameLayout subclass, chính nó là lớp con của ViewGroup.
  4. Người tiếp theo nhận thông báo (sửa tôi nếu tôi sai) là chế độ xem nội dung hoạt động của bạn. Đó là những gì bạn đặt làm bố cục gốc của hoạt động trong xml khi bạn tạo bố cục trong Trình chỉnh sửa bố cục của Android Studio. Vì vậy, cho dù bạn chọn một RelativeLayout, một LinearLayout hoặc ConstraintLayout, tất cả chúng đều là các lớp con của ViewGroup. Và ViewGroup được thông báo về sự kiện cảm ứng trong dispatchTouchEvent(). Đây là ViewGroup A trong sơ đồ của tôi ở trên.
  5. ViewGroup sẽ notify any children nó có sự kiện liên lạc, bao gồm bất kỳ ViewGroup trẻ em nào. Đây là ViewGroup B trong sơ đồ của tôi ở trên.
  6. Bất kỳ nơi nào trên đường đi, ViewGroup có thể short-circuit quy trình thông báo bằng cách trả lại true cho onInterceptTouchEvent().
  7. Giả sử không có ViewGroup cắt thông báo ngắn, đầu tự nhiên của dòng cho thông báo là khi Chế độ xem của dispatchTouchEvent() được gọi.
  8. Bây giờ là lúc, để bắt đầu xử lý các sự kiện. If there is an OnTouchListener, sau đó nó là cơ hội đầu tiên xử lý sự kiện liên lạc với onTouch(). Otherwise, Chế độ xem của onTouchEvent() được xử lý.
  9. Bây giờ tất cả các Nhóm xem theo cách đệ quy lên đường có cơ hội xử lý sự kiện chạm theo cùng cách mà View đã làm. Mặc dù, tôi không cho biết điều này trong sơ đồ trên, một số ViewGroup là một phân lớp View, vì vậy mọi thứ tôi mô tả về OnTouchListener.onTouch()onTouchEvent() cũng áp dụng cho Nhóm xem.
  10. Finally, nếu không ai khác muốn, Hoạt động cũng là cơ hội cuối cùng để xử lý sự kiện với onTouchEvent().

FAQ

Khi nào tôi đã từng cần phải ghi đè dispatchTouchEvent()?

Có thể bạn sẽ không cần, trừ khi bạn cần thực hiện thêm một số định tuyến không xảy ra theo mặc định. Để theo dõi thông báo sự kiện chạm, bạn có thể ghi đè lên onInterceptTouchEvent().

Khi nào tôi cần ghi đè onInterceptTouchEvent()?

Nếu bạn chỉ muốn theo dõi các thông báo chạm đang đến, bạn có thể thực hiện tại đây và trả lại false.

Tuy nhiên, mục đích chính của việc ghi đè phương pháp này là để cho ViewGroup xử lý một loại sự kiện chạm nhất định trong khi cho phép đứa trẻ xử lý một loại khác. Ví dụ, một ScrollView thực hiện điều này để xử lý cuộn trong khi để con của nó xử lý một cái gì đó giống như một nút bấm. Ngược lại, nếu chế độ xem con không muốn để cha mẹ đánh cắp sự kiện liên lạc của nó, nó có thể gọi requestDisallowTouchIntercept().

Các loại sự kiện chạm là gì?

Những cái chính là

  • ACTION_DOWN - Đây là khởi đầu của một sự kiện liên lạc. Bạn phải luôn trả lại true cho sự kiện ACTION_DOWN trong onTouchEvent nếu bạn muốn xử lý sự kiện chạm. Nếu không, bạn sẽ không nhận được thêm bất kỳ sự kiện nào được gửi cho bạn.
  • ACTION_MOVE - Sự kiện này liên tục bị kích hoạt khi bạn di chuyển ngón tay trên màn hình.
  • ACTION_UP - Đây là sự kiện cuối cùng của sự kiện liên lạc.

Nhân vật thứ hai là ACTION_CANCEL. Điều này được gọi nếu một ViewGroup lên cây quyết định chặn sự kiện cảm ứng.

Bạn có thể xem các loại MotionEvents khác here. Vì Android đa chạm, các sự kiện cũng được kích hoạt khi các ngón tay khác ("con trỏ") chạm vào màn hình.

Tiếp tục nghiên cứu

Các vấn đề liên quan