今天主要是分析一下Launcher里面的所有應用列表。Android4.0 Launcher的所有應用列表跟2.X比較大的區別就是多了Widget的顯示。下面會詳細分析Launcher里面有關所有應用列表配置和代碼分析。
1、AllApp列表配置文件
配置AllAPP應用列表界面的配置文件是\res\Layout\apps_customize_pane.xml文件。AllAPP列表使用了一個TabHost組織了兩個頁面(全部應用和Widget),通過界面上面的TabHost進行切換。下面是TabHost的配置和AllAPP界面配置,我這里需要把Widget部分功能取消,因為我做的Launcher把Widget放到workspace里面實現了。
//Edited by mythou
//http://www.cnblogs.com/mythou/
<!-- 取消TabHost的顯示,把TabHost設置為0dp高,避免影響all app顯示 mythou --> <com.android.launcher2.AppsCustomizeTabHost android:background="@android:color/transparent"> <LinearLayout android:id="@+id/apps_customize_content" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<!-- TabHost欄,配置TahHost欄的高度寬度
我這里把TabHost取消了,因為我的Launcher需要把Widget反正workspace里面實現,
所以全部應用列表修改成和2.X的Launcher一樣 mythou--> <FrameLayout android:id="@+id/tabs_container" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="0dp" android:layout_gravity="center_horizontal">
<!-- TabHost上面Widget 的按鈕--> <com.android.launcher2.FocusOnlyTabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="left" android:background="@android:color/transparent" android:tabStripEnabled="false" android:tabStripLeft="@null" android:tabStripRight="@null" android:divider="@null" />
<!--TabHost 右邊的Android市場的圖標,不需要可以去掉--> <include android:id="@+id/market_button" layout="@layout/market_button" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="right" /> </FrameLayout>
<!--下面這里就是我們所有應用列表的選項和所有應用列表的顯示View
需要注意的是AppsCustomizePagedView同時支持顯示所有應用列表和Widget列表 mythou--> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="match_parent" >
<!-- 所有應用列表是通過自定義VIewAppsCustomizePagedView顯示,后面會詳細分析這個View
下面只對部分重要屬性加入注釋--> <com.android.launcher2.AppsCustomizePagedView android:id="@+id/apps_customize_pane_content" android:layout_width="match_parent" android:layout_height="match_parent"
//MaxAppCellCountX 和MaxAppCellCounY指的是所有App圖標排列的最大行列數。
//一般設置為-1,表示無限制 launcher:maxAppCellCountX="@integer/apps_customize_maxCellCountX" launcher:maxAppCellCountY="@integer/apps_customize_maxCellCountY"
//pageLayoutWidthGap和pageLayoutHeightGap分別表示菜單界面與屏幕邊緣的距離,
//一般小屏幕這里設置為-1。避免邊框太窄誤觸屏幕才需要設置。 launcher:pageLayoutWidthGap="@dimen/apps_customize_pageLayoutWidthGap" launcher:pageLayoutHeightGap="@dimen/apps_customize_pageLayoutHeightGap" launcher:pageLayoutPaddingTop="50dp"
//pageLayoutPaddingXXX指的是內填充,這個和系統的padding一樣 launcher:pageLayoutPaddingBottom="@dimen/apps_customize_pageLayoutPaddingBottom" launcher:pageLayoutPaddingLeft="@dimen/apps_customize_pageLayoutPaddingLeft" launcher:pageLayoutPaddingRight="@dimen/apps_customize_pageLayoutPaddingRight"
//widgetCellWithGap和widgetCellHeightGap指的是widget列表界面各個widget之間的間隔,
//和系統的margin屬性類似 launcher:widgetCellWidthGap="@dimen/apps_customize_widget_cell_width_gap" launcher:widgetCellHeightGap="@dimen/apps_customize_widget_cell_height_gap"
//widgetCountX和WidgetCountY都是表示Widget界面每行每列顯示多少Widget launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x" launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
//提示界面的焦點 launcher:clingFocusedX="@integer/apps_customize_cling_focused_x" launcher:clingFocusedY="@integer/apps_customize_cling_focused_y" launcher:maxGap="@dimen/workspace_max_gap" />
<!-- 加載全部應用時的旋轉動畫 --> <FrameLayout android:id="@+id/animation_buffer" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FF000000" android:visibility="gone" /> <!-- 分頁符,代表多少頁和當前頁面--> <include android:id="@+id/paged_view_indicator" layout="@layout/scroll_indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" /> </FrameLayout> </LinearLayout> <!--第一次進入所有應用列表的提示界面,和workspace提示界面一樣--> <include layout="@layout/all_apps_cling" android:id="@+id/all_apps_cling" android:layout_width="match_parent" android:layout_height="match_parent"/> </com.android.launcher2.AppsCustomizeTabHost>
上面已經針對TabHost的配置文件給了詳細注釋,這里需要說明的一點是,不管是所有應用列表還是Widget列表都是通過AppsCustomizedPagedView顯示出來,也就是說這個自定義View支持兩種形式顯示。下面我們先對AppsCustomizeTabHost做個簡單分析。
2、AppsCustomizeTabHost分析
AppsCustomizeTabHost是繼承了TabHost的之類,主要是對TabHost進行擴展,增加一些功能。AppsCustomizeTabHost的代碼不多,這里主要對生成AllAPP和Widget頁面選項部分介紹一下。
//Edited by mythou
//http://www.cnblogs.com/mythou/
protected void onFinishInflate() { //.......//創建所有應用列表Tab mythou TextView tabView; String label; label = mContext.getString(R.string.all_apps_button_label); tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false); tabView.setText(label); tabView.setContentDescription(label); addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory)); //Widget的Tab頁面 label = mContext.getString(R.string.widgets_tab_label); tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false); tabView.setText(label); tabView.setContentDescription(label); addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory)); //設置監聽器 setOnTabChangedListener(this); AppsCustomizeTabKeyEventListener keyListener = new AppsCustomizeTabKeyEventListener(); View lastTab = tabs.getChildTabViewAt(tabs.getTabCount() - 1); lastTab.setOnKeyListener(keyListener); //Android商店按鈕 View shopButton = findViewById(R.id.market_button); shopButton.setOnKeyListener(keyListener); // Hide the tab bar until we measure mTabsContainer.setAlpha(0f); }
onFinishInflate回調函數里面執行了創建TabHost需要的Tab View,這個函數在View加載完配置文件的時候會執行。除了創建TabHost外,還有幾個函數需要注意了解。
3、Tab變化時執行onTabChanged
在TabHost切換選項的時候,會執行onTabChanged回調函數,這里執行了切換頁面的操作,具體切換其實是切換AppsCustomizedPagedView類里面的切換,因為所有應用和Widget都是依靠AppsCustomizedPagedView來顯示。onTabChanged里面有兩個地方需要注意一下:
//Edited by mythou
//http://www.cnblogs.com/mythou/
public void onTabChanged(String tabId) { //使用Runnable執行一個切換的動畫效果,因為切換的時候會存在數據加載導致的延時問題。
//在加載切換數據的過程中,加入動畫可以增強用戶體驗 mythou post(new Runnable() { @Override public void run() { ArrayList<View> visiblePages = new ArrayList<View>(); for (int i = visiblePageRange[0]; i <= visiblePageRange[1]; i++) { visiblePages.add(mAppsCustomizePane.getPageAt(i)); } //保證每個頁面都是使用統一的動畫效果 mAnimationBuffer.scrollTo(mAppsCustomizePane.getScrollX(), 0); // mAppsCustomizePane顯示子頁面是使用相反的順序,所以添加頁面動畫的時候, //也是使用相反的添加順序 for (int i = visiblePages.size() - 1; i >= 0; i--) { View child = visiblePages.get(i); //增加切換動畫緩存,提供下面切換動畫使用 mAnimationBuffer.addView(child, p); } // Toggle the new content onTabChangedStart(); onTabChangedEnd(type); //過渡動畫開始 ObjectAnimator outAnim = ObjectAnimator.ofFloat(mAnimationBuffer, "alpha", 0f); //。。。。。。。。 }
onTabChanged主要是提供了一個切換頁面的動畫,以為切換TabHost的時候,會存在一個加載和切換數據的過程,這個過程需要消耗一定時間,所以開了一個線程來執行一個過渡動畫,增強用戶體驗。Launcher里面很多切換操作都存在類似的操作,每個操作都伴隨着一個動畫效果。主要目的就是讓用戶覺得界面操作流暢。
4、onLauncherTransitionStart和onLauncherTransitionEnd
這兩個方法是在Launcher.java類里面調用的,具體調用時機就是從workspace切換到AllAPP列表的時候,切換前會調用onLauncherTransitionStart方法,切換后也會調用onLauncherTransitionEnd。看名字我們大概也能猜出這兩個方法的作用,也是提供一個過渡的動畫效果。onLauncherTransitionEnd還會調用提示界面。
今天就講到這里,下次會開始進入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)
Edited by mythou
原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3182286.html