接着上一篇文章,繼續分析AllAPP列表界面。上一篇文章分析了所有應用列表的界面構成以及如何通過配置文件修改屬性。今天主要是分析PagedViewWithDraggableItems類,因為在我們分析AppsCustomizePagedView之前,需要先了解PagedViewWithDraggableItems。這是因為他們是繼承關系。我們先看看AppsCustomizePagedView的類繼承關系。(以后博客的圖片都會加上水印,因為發現很多轉載文章的人把所有作者信息都刪除了,鄙視這種行為 ╭∩╮(︶︿︶)╭∩╮)
1、觸摸攔截
從上面的類關系圖我們可以看到,我們今天需要分析的PagedViewWithDraggableItems類是繼承了PagedView類。PagedView我在第六篇文章里面已經做了詳細分析。PagedView里面主要就是實現了界面滑動操作,PagedView把頁面滑動的消息在onInterceptTouchEvent()里面攔截了,然后在onTouchEvent()里面進行滑動頁面的處理。既然PagedViewWithDraggableItems也是繼承PagedView,我們先看看PagedViewWithDraggableItems有關觸摸事件的攔截和處理。
//Edited by mythou
//http://www.cnblogs.com/mythou/
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(OWL_DEBUG) Log.d(OWL, "enter- onInterceptTouchEvent "); handleTouchEvent(ev); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { if(OWL_DEBUG) Log.d(OWL, "enter- onTouchEvent "); handleTouchEvent(ev); return super.onTouchEvent(ev); }
PagedViewWithDraggableItems的onInterceptTouchEvent和onTouchEvent處理都很簡單,而且都調用了同一個處理方法。調用完handleTouchEvent(ev)方法后,會直接調用父類的相對應接口。父類的接口也就是PagedView的接口,這兩個攔截觸摸消息的回調方法,我們在上一篇文章已經做了很詳細分析,這里不再多說。根據代碼執行順序,我們可以知道,界面會先調用PagedViewWithDraggableItems的onInterceptTouchEvent方法並且做了一些額外處理,然后才會調用PagedView的處理。下面我們看看PagedViewWithDraggableItems的handleTouchEvent方法做了什么事。
2、handleTouchEvent方法
//Edited by mythou
//http://www.cnblogs.com/mythou/
private void handleTouchEvent(MotionEvent ev) { final int action = ev.getAction(); if(OWL_DEBUG) Log.d(OWL, "handleTouchEvent action="+(action & MotionEvent.ACTION_MASK)+ " mTouchState="+mTouchState+" mIsDragging="+mIsDragging+" mIsDragEnabled="+mIsDragEnabled); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: //按下事件處理 cancelDragging(); mIsDragEnabled = true; break; case MotionEvent.ACTION_MOVE: //進入滑動狀態 if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging && mIsDragEnabled) {
//根據是否進入滾動狀態,判斷是否需要拖曳按鈕 if(OWL_DEBUG) Log.d(OWL, "handleTouchEvent--->before drag "); determineDraggingStart(ev); } else { if(OWL_DEBUG) Log.d(OWL, "handleTouchEvent--->Not drag "); } break; } }
從上面代碼我們可以看到handleTouchEvent里面判斷了兩種觸摸狀態:ACTION_DOWN和ACTION_MOVE。在ACTION_DOWN的時候會清理有關拖動圖標的標記。而在ACTION_MOVE的時候,會根據當前TouchState是不是滾動狀態,如果不是,進入拖動圖標操作。TouchState是根據PagedView里面的狀態判斷的,這個我們分析TouchState的時候已經分析過。下面我們看看代碼調用流程,下面是我加了打印消息后,LogCat的消息:
上面是我結合PagedView類和PagedViewWithDraggableItems類對一次界面滑動的代碼跟蹤 ,我們可以看到系統先調用PagedViewWithDraggableItems的onInterceptTouchEvent然后依次調用上面分析的代碼。需要注意的是上面LogCat高亮喊信息里面,會跑到handleTouchEvent的ACTION_MOVE,然后調用determineDraggingStart()方法。不過這里並不會調用PagedViewWithDraggableItems的determineDraggingStart()方法,而且調用了AppsCustomizedPagedView的方法,因為在AppsCustomizedPagedView里面把這個方法重寫了。是一個空方法。
4、拖曳按鈕
上面分析的流程是滑動界面執行的代碼流程,下面我們看看如果你需要拖曳一個按鈕,會怎么樣。Android里面拖曳一個按鈕,首先需要除非LongClick消息,也就是需要長按按鈕才行。下面我們跟蹤LogCat消息看看代碼運行情況:
//Edited by mythou
//http://www.cnblogs.com/mythou/
@Override public boolean onLongClick(View v) { if(OWL_DEBUG) Log.d(OWL, "onLongClick Enter"); //下面有幾種情況會取消長按觸摸,不是觸摸狀態,正在動畫過渡,離開了allAPP頁面 if (!v.isInTouchMode()) return false; // Return early if we are still animating the pages if (mNextPage != INVALID_PAGE) return false; // When we have exited all apps or are in transition, disregard long clicks if (!mLauncher.isAllAppsCustomizeOpen() || mLauncher.getWorkspace().isSwitchingState()) return false; if(OWL_DEBUG) Log.d(OWL, "onLongClick beginDragging()"); //調用開始拖曳的設置,里面會設置一些標記 return beginDragging(v); }
PagedViewWithDraggableItems的onLongClick()方法,只是執行了簡單的標記設置。到這里應該可以了解PagedViewWithDraggableItems主要的作用,因為Launcher里面很大一部分功能就是對於這種手勢操作的處理,所以有必要認真分析這幾個基類。為后面分析AppsCustomizedPagedView打好基礎。
Launcher分析系列文章:
Android Launcher分析和修改1——Launcher默認界面配置(default_workspace)
Android Launcher分析和修改2——Icon修改、界面布局調整、壁紙設置
Android Launcher分析和修改3——Launcher啟動和初始化
Android Launcher分析和修改4——初始化加載數據
Android Launcher分析和修改5——HotSeat分析
Android Launcher分析和修改6——頁面滑動(PagedView)
Android Launcher分析和修改7——AllApp全部應用列表(AppsCustomizeTabHost)
Edited by mythou
原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3183081.html