Android自己定义组件系列【6】——进阶实践(3)
上一篇《Android自己定義組件系列【5】——進階實踐(2)》繼續對任老師的《可下拉的PinnedHeaderExpandableListView的實現》進行了分析,這一篇計劃中間插一段“知識點”,對Android中的事件分發機制進行解析。
細心的朋友可能會發現。打開大牛寫的Android項目,里面非常多組件都是自己定義的(這就是為什么界面和體驗這么吸引你的原因)。可是要靈活的去自己定義組件就必須對手勢(也就是各種監聽)必須熟悉,能處理好事件之間的關系。
先看一段代碼:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {Log.i(TAG, "onClick");}});button.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.i(TAG, "onTouch down");break;case MotionEvent.ACTION_MOVE:Log.i(TAG, "onTouch move");break;case MotionEvent.ACTION_UP:Log.i(TAG, "onTouch up");break;default:break;}return false;}});}能夠看到onTouch方法會被先調用,然后才調用onClick方法。假設我們將上面onTouch方法的返回值改為true,則onClick方法不會被調用。事件將被onTouch方法消費。
還記得前幾篇文章中都會使用一個dispatchTouchEvent的方法嗎.
public boolean dispatchTouchEvent(MotionEvent event) {if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&mOnTouchListener.onTouch(this, event)) {return true;}return onTouchEvent(event); }能夠看到在dispatchTouchEvent中調用了onTouch方法,所以會先于onClick方法調用。假設onTouch返回true后dispatcheTouchEvent就會直接返回true則不會再運行其它方法。
在Android系統中每一個ViewGroup子類都具有例如以下三個方法:
public boolean dispatchTouchEvent(MotionEvent event) ?:用來分發TouchEvent
public boolean onInterceptTouchEvent(MotionEvent event) :用來攔截TouchEvent
public boolean onTouchEvent(MotionEvent event) :處理TouchEvent
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <com.kris.touch.widget.TouchView android:id="@+id/view_out" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#fff" android:gravity="center"> <com.kris.touch.widget.TouchView android:id="@+id/view_mid" android:layout_width="300px" android:layout_height="400px" android:background="#f00" android:gravity="center"> <com.kris.touch.widget.TouchView android:id="@+id/view_center" android:layout_width="150px" android:layout_height="150px" android:background="#000" android:gravity="center" android:clickable="true"> </com.kris.touch.widget.TouchView> </com.kris.touch.widget.TouchView> </com.kris.touch.widget.TouchView> </LinearLayout>
首先觸摸事件(ACTION_DOWN)發生后。系統調用Activity的dispatchTouchEvent方法,分發事件。依據觸摸事件的坐標,將此事件傳遞給out(最外層)的dispatchTouchEvent處理。out則調用onInterceptTouchEvent方法推斷事件是否由自己來處理。還是向下傳遞給子View.假設out不處理該事件會依據事件產生坐標分發給它的直接子View.
圖中center組件是可點擊的(clickable)組件。表示能處理Touch事件,所以center中的onInterceptTouchEvent方法將事件傳遞給center
TouchEvent中。假設返回值是true,則說明消耗(消費)了這個事件,不會再向下傳遞。假設返回值是false,則沒有消耗事件,會繼續傳遞下去。假設center中不會處理事件(android:clickable="false"),事件不會被center的onTouchEvent消費,則事件會層層逆向回到activity。
關于事件分發機制就先了解到這里,下一篇接著分析......
總結
以上是生活随笔為你收集整理的Android自己定义组件系列【6】——进阶实践(3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 7编程模式与实践
- 下一篇: 微服务,微架构[五]之springboo