【原始碼剖析】Launcher 8.0 原始碼 (10) --- Launcher 啟動流程 第四步之桌面佈局(2)
本篇講解Launcher啟動流程第四步setupViews方法中的第二部分 setupOverviewPanel();這個方法。
對於setupOverviewPanel()方法主要操作就是對overViewPanel佈局裡面的空間進行事件的繫結。對於OverViewPanel的佈局整體在res裡面以xml檔案的形式存在。
什麼是OverViewPanel那?
在Launcher使用時,長按桌面空白處,此時workspace縮小,hotseat消失,在下方出現三個選項,wallpapers,widget,setting,這個提供特殊選項的欄就叫做overviewpanel

5128077-1dbf7225ef982b69.png
setupOverviewPanel()
我們來看下 setupOverviewPanel()方法的原始碼。通關觀察,我們發現整個方法思路很清晰,首先獲取overview_panel的View,然後依次建立wallpaper,widget,settings這3個buttom。給button設定點選事件。
private void setupOverviewPanel() { mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel); 1.// Bind wallpaper button actions View wallpaperButton = findViewById(R.id.wallpaper_button); new OverviewButtonClickListener(ControlType.WALLPAPER_BUTTON) { @Override public void handleViewClick(View view) { onClickWallpaperPicker(view); } }.attachTo(wallpaperButton); 2.// Bind widget button actions mWidgetsButton = findViewById(R.id.widget_button); new OverviewButtonClickListener(ControlType.WIDGETS_BUTTON) { @Override public void handleViewClick(View view) { onClickAddWidgetButton(view); } }.attachTo(mWidgetsButton); 3. // Bind settings actions View settingsButton = findViewById(R.id.settings_button); boolean hasSettings = hasSettings(); if (hasSettings) { new OverviewButtonClickListener(ControlType.SETTINGS_BUTTON) { @Override public void handleViewClick(View view) { onClickSettingsButton(view); } }.attachTo(settingsButton); } else { settingsButton.setVisibility(View.GONE); } mOverviewPanel.setAlpha(0f); }
第一步建立wallpaperButton
通過findViewById找到控制元件wallpaper_button,建立Listener,並繫結到view上。new OverviewButtonClickListener().attachTo(wallpaperButton).
在attachTo方法中會給View設定長按點選事件和點選事件
public void attachTo(View v) { v.setOnClickListener(this); v.setOnLongClickListener(this); }
那麼點選事件的具體實現是在OverviewButtonClickListener這個類中,那麼就來看一下這兩個方法
@Override public void onClick(View view) { if (shouldPerformClick(view)) { handleViewClick(view, Action.Touch.TAP); } } @Override public boolean onLongClick(View view) { if (shouldPerformClick(view)) { handleViewClick(view, Action.Touch.LONGPRESS); } return true; }
兩個方法裡面都呼叫了handleViewClick方法,而我們建立的OverviewButtonClickListener則是重寫了handleViewClick方法。
public void handleViewClick(View view) {
onClickWallpaperPicker(view);
}
於是,這裡建立物件並attach,就是當我們點選這個按鈕時,要觸發重寫的方法。在wallpaperButton裡面,我們寫的是onClickWallpaperPicker(view)。
我們來看一下onClickWallpaperPicker(view)方法原始碼,只貼上最關鍵程式碼
public void onClickWallpaperPicker(View v) { Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER) .putExtra(Utilities.EXTRA_WALLPAPER_OFFSET, offset); startActivityForResult(intent, REQUEST_PICK_WALLPAPE hasTargetPackage ? getActivityLaunchOptions(v) : null); }
主要操作是通過Intent跳轉到設定桌布功能的應用。
第二步建立mWidgetsButton
整個步驟和第一步基本一樣,只有handelViewClick中重寫的內容不一樣,這裡會呼叫 onClickAddWidgetButton(view);方法。
public void onClickAddWidgetButton(View view) { showWidgetsView(true /* animated */, true /* resetPageToZero */); } void showWidgetsView(boolean animated, boolean resetPageToZero) { showAppsOrWidgets(State.WIDGETS, animated, false); } private boolean showAppsOrWidgets(State toState, boolean animated, boolean focusSearchBar) { if (toState == State.APPS) { mStateTransitionAnimation.startAnimationToAllApps(animated, focusSearchBar); } else { mStateTransitionAnimation.startAnimationToWidgets(animated); } return true; }
從程式碼可以看到,是一個遞進呼叫,過程中對state進行設定,最終呼叫了mStateTransitionAnimation這個物件的方法。
mStateTransitionAnimation是在Launcher流程第三步建立的第三個物件,負責不同模式間的切換,在onClickAddWidgetButton中完成的是從overview模式到widget模式的切換。
第三步建立settingsButton
最後是settingsButton
public void onClickSettingsButton(View v) { if (LOGD) Log.d(TAG, "onClickSettingsButton"); Intent intent = new Intent(getApplicationContext(), HomescreenSettingsActivity.class); intent.setSourceBounds(getViewBounds(v)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent, getActivityLaunchOptions(v)); showWorkspace(true); }
通過intent跳轉到設定頁面。
這樣overviewpanel的三個選項就都完成了。其中wallpapers和settings是啟動新的activity , widget是Launcher之間的模式變化