android自訂控制項系列教程-----touch事件的傳遞

來源:互聯網
上載者:User

android自訂控制項系列教程-----touch事件的傳遞
前沿:很久沒有寫過部落格了,因為工作的原因很少有時間寫東西了,最近想寫一個UI系列的部落格,因為我發現這一系列的都很少,而且沒有那麼系統,這裡我想以我自己的觀點來闡述一下如何自訂android 控制項系列。自訂控制項闡述:在我的理解裡面自訂控制項,需要瞭解到touch事件的傳遞、分發、攔截機制,Scroller類的運用,andorid 視圖的理解,ViewGroup的熟悉,因為我們絕大多的控制項都是繼承自ViewGroup,還有就是要學會布局測量等。Touch事件的傳遞首先我們要瞭解在android系統裡面有幾個地方會走touch事件,這個是老生常談的問題了,但是我還是希望寫一下這個問題,因為溫故而知新嘛,我們首先得知道VIew類這種不能作為容器的類只會有這兩個函數:

@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {// TODO Auto-generated method stubreturn super.dispatchTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubreturn super.onTouchEvent(event);}
而能做為容器的類如ViewGroup以及繼承它的類會有這幾個函數:
@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubreturn super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubreturn super.onTouchEvent(event);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubreturn super.dispatchTouchEvent(ev);}
現在我們就分別來重寫這幾個函數分別走一遍流程,讓我們更能清楚的看到android的touch事件是怎麼傳遞的。我們來重寫一下這兩類的方法。重寫一個TextView
public class MyTextView extends TextView{private final String TAG = MyTextView.class.getSimpleName();public MyTextView(Context context) {super(context);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_DOWN");break;case MotionEvent.ACTION_POINTER_DOWN:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_POINTER_DOWN");break;case MotionEvent.ACTION_POINTER_UP:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_POINTER_UP");break;case MotionEvent.ACTION_MOVE:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_UP");break;}return super.dispatchTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d(TAG, TAG + "onTouchEvent+ACTION_DOWN");break;case MotionEvent.ACTION_POINTER_DOWN:Log.d(TAG, TAG + "onTouchEvent+ACTION_POINTER_DOWN");break;case MotionEvent.ACTION_POINTER_UP:Log.d(TAG, TAG + "onTouchEvent+ACTION_POINTER_UP");break;case MotionEvent.ACTION_MOVE:Log.d(TAG, TAG + "onTouchEvent+ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.d(TAG, TAG + "onTouchEvent+ACTION_UP");break;}return super.onTouchEvent(event);}}
然後我們再重寫一個LinearLayout
public class MyLinearLayout extends LinearLayout {private final String TAG = MyLinearLayout.class.getSimpleName();public MyLinearLayout(Context context) {super(context);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d(TAG, TAG + "onInterceptTouchEvent+ACTION_DOWN");break;case MotionEvent.ACTION_POINTER_DOWN:Log.d(TAG, TAG + "onInterceptTouchEvent+ACTION_POINTER_DOWN");break;case MotionEvent.ACTION_POINTER_UP:Log.d(TAG, TAG + "onInterceptTouchEvent+ACTION_POINTER_UP");break;case MotionEvent.ACTION_MOVE:Log.d(TAG, TAG + "onInterceptTouchEvent+ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.d(TAG, TAG + "onInterceptTouchEvent+ACTION_UP");break;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d(TAG, TAG + "onTouchEvent+ACTION_DOWN");break;case MotionEvent.ACTION_POINTER_DOWN:Log.d(TAG, TAG + "onTouchEvent+ACTION_POINTER_DOWN");break;case MotionEvent.ACTION_POINTER_UP:Log.d(TAG, TAG + "onTouchEvent+ACTION_POINTER_UP");break;case MotionEvent.ACTION_MOVE:Log.d(TAG, TAG + "onTouchEvent+ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.d(TAG, TAG + "onTouchEvent+ACTION_UP");break;}return super.onTouchEvent(event);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_DOWN");break;case MotionEvent.ACTION_POINTER_DOWN:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_POINTER_DOWN");break;case MotionEvent.ACTION_POINTER_UP:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_POINTER_UP");break;case MotionEvent.ACTION_MOVE:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.d(TAG, TAG + "dispatchTouchEvent+ACTION_UP");break;}return super.dispatchTouchEvent(ev);}}


public class TestActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);MyLinearLayout layout = new MyLinearLayout(this);MyTextView myTextView = new MyTextView(this);myTextView.setText("touch event");layout.addView(myTextView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));setContentView(layout);}}
我們來看看log然後我們在把TextView改成Button來看一下然後在看一下log分析上面的log我們看到,touch事件首先走到的是父親的dispatchTouchEvent方法中,然後是onInterceptTouchEvent過後才是MyTextView的dispatchTouchEvent和TouchEent中。所以我們知道了一件事:那就是所有的touch事件一定是先傳遞給父親然後在傳遞給孩子,然後在分析函數執行的順序最開始執行的是dispatchTouchEvent方法,後面執行onInterceptTouchEvent最後才走到onTouchEvent事件當中。同時我們也要注意這幾個函數的的返回值是boolean變數。然後我們再把MyLinearLayout的dispatchTouchEvent方法的返回值返回true,跑一下。

你會看到事件始終都只在MyLinearLayout裡面了,根本就沒有傳遞到孩子裡面去了。同樣我們把它返回false,試試

這時候看到只有down事件了,這說明了什麼呢?當dispatchTouchEvent返回true的時候會繼續傳遞事件給自身控制項dispatchTouchEvent處理,就像剛才的MylinearLayout一樣仍然可以執行,DOWN和UP事件,當我們返回了false就連自身控制項都不能接收到事件了。同樣我們把dispatchTouchEvent還原,然後在onInterceptTouchEvent裡面返回true;

可以看到事件也只分發到自身控制項並進入到自身的OntouchEvent中,然後我們在把onInterceptTouchEvent的返回值改為false,看看結果

可以看到我們的事件沒有收到任何影響所有的都照常執行,同樣把MylinearLayout中的onInterceptTouchEvent複原,現在注意了我們要修改的是MyTextView中的onTouchEvent的返回值,我們把它修改為true

可以看到也沒有任何變化,我們在試試把它改為false。

可以看到MytextView只接收到DOWN事件就再也不會接收到其他事件了。結論:androidtouch事件的預設行程順序的父親控制項到子控制項,而函數的調用順序大致是這樣的dispatchTouchEvent---->訊息分發--->onInterceptTouchEvent--->事件打斷-->onTouchEvent-->>事件處理。關於返回值的問題我來簡單的總結一下剛才上面的實驗和結論:dispatchTouchEvent返回的是true的時候事件是不會繼續往下面傳遞了,一直都會走本身的dispatchTouchEvent這個方法,當返回為false的時候只會走一次dispatchTouchEvent這個方法的Down事件:onInterceptTouchEvent返回的是true的時候是把事件攔截了讓他走自身的onTouchEvent方法,當他返回為false的方法的時候不進行攔截正常進行。 onTouchEvent這個方法的返回值是true的時候,繼續分發事件到自身的touchEvent中,當為false的時候只會分發第一次down事件,還有各種返回值的組合我就不一一舉例了,要想寫好自訂的UI和控制項touch事件的分發是必須得學好的,剩下的就慢慢的自己體會把。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.