1. 程式人生 > >【原始碼剖析】Launcher 8.0 原始碼 25---使用者操作(2)模式切換

【原始碼剖析】Launcher 8.0 原始碼 25---使用者操作(2)模式切換

 模式就是介面,除普通模式外,Launcher還有兩個特殊模式,分別是overView模式和Springloader模式。此處採用狀態模式這種設計模式,共有三個狀態。

overView模式是長按桌面空白處,出現特殊功能,比如設定桌布,新增widget,特殊設定(橫屏開關,負一屏開關等),設定主螢幕(點選home鍵自動移動到的cellLayout),刪除螢幕等。

Springloader模式又叫拖拽模式,使用者想改變CellLayout裡面的佈局,就是通過拖拽圖示,widget等來改變其位置,這個模式叫做拖拽模式。

正常模式,overView模式和SpringLoader模式就構成了正常的Launcher三個核心互動。

點選和滑動構成了普通模式,而長按則是overView模式和SpringLoader模式的起始因素。

Launcher 實現了OnLongClickListener介面。

原始碼如下:

@Override public boolean onLongClick(View v) { //首先進行三種判斷,其實質:如果當前狀態處於其他狀態返回Launcher狀態的途中,或者Launcher的佈局還沒有讀取完成,則不進行後續操作。因為在以上兩種狀態,進行後面的操作會出故障,此外,以上兩種狀態持續時間非常短暫,所以考慮為使用者誤操作且這一瞬間操作無用。  比如說拖拽完圖示後,我們能看到從springload模式進入普通模式的過程,這個過程中,長按桌面是沒有任何作用的。

if (!isDraggingEnabled()) return false;     if (isWorkspaceLocked()) return false;     if (mState != State.WORKSPACE) return false;

//後面判斷方法和onclick有些類似,一次判斷是點選的哪裡來進行對應處理,首先如果長按的是allapp入口,則開啟allapp。對於allapp按鈕,點選和長按一個效果。Allapp按鈕在Launcher8.0裡是hotseat上面的indicator上面的小三角符號。

    if ((FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && v instanceof PageIndicator) ||             (v == mAllAppsButton && mAllAppsButton != null)) {         onLongClickAllAppsButton(v);

        return true;     } //如果使用者點選的是桌面空白處,則從普通模式進入overView模式,也是手機裡面的長按空白出現下方快捷操作欄的行為,這是最常見的操作。     if (v instanceof Workspace) {         if (!mWorkspace.isInOverviewMode()) {             if (!mWorkspace.isTouchActive() && !ignoreLongPressToOverview) {                 getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,                         Action.Direction.NONE, ContainerType.WORKSPACE,                         mWorkspace.getCurrentPage());                 showOverviewMode(true);                 mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,                         HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);                 return true;             } else {                 return false;             }         } else {             return false;         }     } //如果點選的是item,這個item就是Launcher啟動模式裡面loadAndBindWorkspace所load和bind的item。如果點選Launcher就獲取 longClickCellInfo 。具體程式碼還在後面。     CellLayout.CellInfo longClickCellInfo = null;     View itemUnderLongClick = null;     if (v.getTag() instanceof ItemInfo) {         ItemInfo info = (ItemInfo) v.getTag();         longClickCellInfo = new CellLayout.CellInfo(v, info);         itemUnderLongClick = longClickCellInfo.cell;         mPendingRequestArgs = null;     }     if (!mDragController.isDragging()) {         if (itemUnderLongClick == null) { //如果在overview模式,且長按了頁面,則進入頁面調整模式。長按的頁面(cellLayout)會有視效變化,同時提供頁面(cellLayout)交換的功能。             if (mWorkspace.isInOverviewMode()) {                 mWorkspace.startReordering(v);                 getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,                         Action.Direction.NONE, ContainerType.OVERVIEW);             } else {

//如果在overview模式長按空白處,則仍然停留在overview模式。                 if (ignoreLongPressToOverview) {                     return false;                 }                 getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,                         Action.Direction.NONE, ContainerType.WORKSPACE,                         mWorkspace.getCurrentPage());                 showOverviewMode(true);             }             mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,                     HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);         } else {

//如果就是在普通模式長按了item,那麼根據之前獲取的longClickCellInfo進入drag模式。也就是springloader模式。             final boolean isAllAppsButton =                     !FeatureFlags.NO_ALL_APPS_ICON && isHotseatLayout(v) &&                             mDeviceProfile.inv.isAllAppsButtonRank(mHotseat.getOrderInHotseat(                                     longClickCellInfo.cellX, longClickCellInfo.cellY));             if (!(itemUnderLongClick instanceof Folder || isAllAppsButton)) {                 // User long pressed on an item                 mWorkspace.startDrag(longClickCellInfo, new DragOptions());             }         }     }     return true; }

以上,Launcher的長按主要是進入overView模式和springloader模式。

overView模式下面能做的事情有,設定主螢幕,刪除螢幕,顯示選項欄等首先在Launcher的啟動流程第四步setupView當中的setupOverviewPanel是對下方選項欄進行定義。

而其中定義了三個按鈕,第一個是wallpapers,其作用是開啟帶有”Intent.ACTION_SET_WALLPAPER”的應用。

第二個是widget列表,其WidgetsContainerView中放有WidgetsRecyclerView。放著當前user下能夠識別的所有widget。根據click原始碼如下,當點選空白處,直接return。而點選到widget上則提示使用者需要長按widget才行。

@Override public void onClick(View v) {     // When we have exited widget tray or are in transition, disregard clicks     if (!mLauncher.isWidgetsViewVisible()             || mLauncher.getWorkspace().isSwitchingState()             || !(v instanceof WidgetCell)) return;     handleClick(); } public void handleClick() {     // Let the user know that they have to long press to add a widget     if (mWidgetInstructionToast != null) {         mWidgetInstructionToast.cancel();     }     CharSequence msg = Utilities.wrapForTts(             getContext().getText(R.string.long_press_widget_to_add),             getContext().getString(R.string.long_accessible_way_to_add));     mWidgetInstructionToast = Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT);     mWidgetInstructionToast.show(); }

如果長按的話,則是進入beginDragging。後面會統一講解各個地方長按的邏輯。到目前可知,allapp長按是進入workspace的drag,而widget長按是進入widget自己的drag。

@Override public boolean onLongClick(View v) {     if (!mLauncher.isWidgetsViewVisible()) return false;     return handleLongClick(v); } public boolean handleLongClick(View v) {     if (!v.isInTouchMode()) return false;     if (mLauncher.getWorkspace().isSwitchingState()) return false;     if (!mLauncher.isDraggingEnabled()) return false;     return beginDragging(v); }

而在folder中的長按則folder自己的長按加上workspace的長按。

當然無論是workspace的長按還是widget的長按最終走入的還是dragControll的長按。

以上就是overviewMode模式的操作,因為overviewMode的操作的實現在Launcher的啟動流程完成。建議本文配合啟動流程的overviewMode建立共同學習。