最近接了一個開發車載導航上的android launcher的工作,Launcher源碼比較多,而且裏面應用了很多設計模式,要把它分析清楚要花不少精力,網上也有一些零碎的分析文章,不過關於修改的文章不多,就想到要把開發和修改的過程通過博客的方式記錄下來,邊開發邊記錄,等開發完之後,再回顧肯定有很大的成就感,好了,廢話不多說,切入正題。
我現在手頭上的launcher的源碼是基於android4.1的,其實4.0,4.1,4.2,乃至4.4的差距並不是很大,但是由於運行系統是4.1的,所以,最好還是基於4.1的版本來開發,由於原生的launcher(以後簡稱桌面好了,比Launcher打的快一點),今天的主要工作就是去掉原生桌面的某些東西(搜索欄目,豎條等),修改hotseat的排列方式。先來看看我的效果圖吧(開發樣機使用的是魅族MX,嘻嘻*-*):
因爲程序是用於車載導航儀的,所以界面和一般的手機界面差別較大。改動也比較大,不過對於Launcher的分析修改都是通用的,大家也將就着看下去吧。這裏也放一下原生桌面的樣子:
接下來,我們就針對界面修改的地方做分析:
一、豎屏改橫屏
這裏其實沒什麼技術含量,就是修改manifest,找到android:screenOrientation這個屬性,將其值修改爲landscape即可
二、去除google search bar
因爲是定製的車載導航需要的launcher,所以這個一直顯示在頂欄的google search bar就顯得比較討厭了,肯定是要去掉的,那麼,要怎麼去掉呢,研究清楚了其實也不復雜:
1. Launcher2\res\layout\qsb_bar.xml中,
1 <include android:id="@+id/qsb_search_bar" 2 layout="@layout/search_bar" 3 android:visibility="gone" />
加入 android:visibility="gone"
2. packages\apps\Launcher2\res\layout-port\launcher.xml
1 <com.android.launcher2.DrawableStateProxyView 2 android:id="@+id/voice_button_proxy" 3 android:layout_width="80dp" 4 android:layout_height="@dimen/qsb_bar_height" 5 android:layout_gravity="top|right" 6 android:clickable="false" //modify this value to false 7 onClick="onClickVoiceButton" 8 android:importantForAccessibility="no" 9 launcher:sourceViewId="@+id/voice_button" />
android:clickable屬性修改爲"false"
3. Launcher2\src\com\android\launcher2\SearchDropTargetBar.java 中onFinishInflate() 方法內,將mQSBSearchBarAnim 相關的部分作如下修改
1 // Create the various fade animations 2 if (mEnableDropDownDropTargets) { 3 mDropTargetBar.setTranslationY(-mBarHeight); 4 mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "translationY", 5 -mBarHeight, 0f); 6 mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "translationY", -mBarHeight , 7 -mBarHeight); //modify 3rd para to -mBarHeight 8 } else { 9 mDropTargetBar.setAlpha(0f); 10 mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 0f, 1f); 11 mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 0f , 0f); //modify 3rd para to 0f; 12 }
4. 仍然是這隻 java 文件,將showSearchBar 方法作如下修改:
1 public void showSearchBar(boolean animated) { 2 3 if (!mIsSearchBarHidden) return; 4 if (animated) { 5 prepareStartAnimation(mQSBSearchBar); 6 mQSBSearchBarAnim.reverse(); 7 } else { 8 mQSBSearchBarAnim.cancel(); 9 if (mEnableDropDownDropTargets) { 10 mQSBSearchBar.setTranslationY(0); 11 } else { 12 mQSBSearchBar.setAlpha( 0f ); //參數改爲 0f; 13 } 14 } 15 mIsSearchBarHidden = false; 16 }
三、hotseat的修改
改完之後,我們會發現hotseat排列到右邊去了,顯的很不美觀是不是?作爲車載導航的launcher,我們肯定是希望hotseat能排布在屏幕的Bottom啊,沒關係,我們來改一下:
首先,我們需要修改Hotseat.java
1 public Hotseat(Context context, AttributeSet attrs, int defStyle) { 2 super(context, attrs, defStyle); 3 4 TypedArray a = context.obtainStyledAttributes(attrs, 5 R.styleable.Hotseat, defStyle, 0); 6 mCellCountX = a.getInt(R.styleable.Hotseat_cellCountX, -1); 7 mCellCountY = a.getInt(R.styleable.Hotseat_cellCountY, -1); 8 mAllAppsButtonRank = context.getResources().getInteger(R.integer.hotseat_all_apps_index); 9 mIsLandscape = false;//context.getResources().getConfiguration().orientation == 10 //Configuration.ORIENTATION_LANDSCAPE; 11 }
注意這裏有一個大屏幕還是小屏幕的判斷,這個是用來判斷屬於平板系統還是一般的手機系統。因爲我係統是只會在橫屏時使用,所以我直接設置成mIsLandscape爲小屏幕,因爲Hotseat裏面很多獲取熟悉都是區分大小屏幕。小屏幕的時候,我們使用豎向配置hotseat就可以得到相當於手機系統的hotseat效果,hotseat會顯示在屏幕底下。
下面我們看看Hotseat的配置文件,Hotseat是屬於workspace的,所以需要在workspace配置文件裏面配置,打開launcher.xml就可以看到hotseat的配置,這個並不是所有launcher.xml文件都有hotseat屬性,如果你的launcher要適配多個分辨率的機器,那麼你就得在適合你機器的分辨率下的相應的目錄下的launcher.xml下添加hotseat屬性。這裏需要將android:layout_height和android:layout_width的屬性對調一下,然後將android:layout_gravity改爲bottom
1 <include layout="@layout/hotseat" 2 android:id="@+id/hotseat" 3 android:layout_height="@dimen/button_bar_height_plus_padding" 4 android:layout_width="match_parent" 5 android:layout_gravity="bottom" />
改完這個還是不夠的,運行的時候,你會發現hotseat圖標都縮到一起去了,還有一個地方也需要修改,layout-land/hotseat.xml也是需要做一下配置改動的
1 <com.launcherjellybean.android.Hotseat 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:launcher="http://schemas.android.com/apk/res/com.launcherjellybean.android" 4 launcher:cellCountX="@integer/hotseat_cell_count" 5 launcher:cellCountY="1"> 6 <com.launcherjellybean.android.CellLayout 7 android:id="@+id/layout" 8 android:layout_width="wrap_content" 9 android:layout_height="match_parent" 10 android:layout_gravity="center" 11 android:paddingTop="@dimen/button_bar_height_top_padding" 12 android:paddingBottom="@dimen/button_bar_height_bottom_padding" 13 android:paddingLeft="@dimen/button_bar_width_left_padding" 14 android:paddingRight="@dimen/button_bar_width_right_padding" 15 16 launcher:cellWidth="@dimen/hotseat_cell_width" 17 launcher:cellHeight="@dimen/hotseat_cell_height" 18 launcher:widthGap="@dimen/hotseat_width_gap" 19 launcher:heightGap="@dimen/hotseat_height_gap" 20 launcher:maxGap="@dimen/workspace_max_gap" /> 21 </com.launcherjellybean.android.Hotseat>
其中launcher:cellCountX的值和launcher:cellCountY是需要對調的,你想想就知道爲什麼了
另外android:layout_height也需要從wrap_content變成match_parent,去查查他們的區別,你就知道爲什麼這麼改了
光是這麼改,也依然不夠,原生桌面圖標是4* 4的佈局,如果把hotseat挪下來,就變成了5 *4的圖標了,顯然,太擁擠了,那麼就需要修改桌面的行列數,打開文件values/config.xml,修改以下2個字段
<integer name="cell_count_x">4</integer> <integer name="cell_count_y">3</integer>
這裏我將cell_count_y從4改成了3,從而讓hotseat佔據了第四行,運行發現除了hotseat那一行的圖標,其餘圖標都排布的比較下面,這是什麼原因呢,這是因爲桌面圖標的高度是自適應居中的,由於我們修改了配置爲3行,那麼桌面圖標自然在上下都留出了相應的高度,以便讓圖標居中了,所以,我們要讓桌面圖標知道,最後一行是被hotseat給佔據了,從而還需要修改launcher.xml這個文件
1 <com.launcherjellybean.android.Workspace 2 android:id="@+id/workspace" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingLeft="@dimen/workspace_left_padding" 6 android:paddingRight="@dimen/workspace_right_padding" 7 android:paddingTop="0dp" 8 android:paddingBottom="60dp" 9 launcher:defaultScreen="1" 10 launcher:cellCountX="@integer/cell_count_x" 11 launcher:cellCountY="@integer/cell_count_y" 12 launcher:pageSpacing="@dimen/workspace_page_spacing" 13 launcher:scrollIndicatorPaddingLeft="@dimen/qsb_bar_height" 14 launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height">
這裏,我修改了android:paddingBottom 和 android:paddingTop這2個值,以讓圖標看起來不會那麼奇怪,這樣,已經成功了一大半了
四、去掉多餘的2根豎線
我們修改完以上的東西,會發現還多了2根豎線,一根是google search bar留下的,另外一根是hotseat剩下的,放在2邊很不美觀,對吧,絕壁要去掉啊!!! 那麼,這2根討厭的豎線在哪呢,它們就藏在launcher.java裏:
1 private View mQsbDivider; 2 private View mDockDivider;
我們找到和這2個變量有關的代碼,全部予以屏蔽即可,比如hideDockDivider() 、showDockDivider()這些之類的,要堅決予以屏蔽,另外在WorkSpace.java裏也發現了它們的身影:
1 void setFadeForOverScroll(float fade) { 2 if (!isScrollingIndicatorEnabled()) return; 3 4 mOverscrollFade = fade; 5 float reducedFade = 0.5f + 0.5f * (1 - fade); 6 final ViewGroup parent = (ViewGroup) getParent(); 7 // final ImageView qsbDivider = (ImageView) (parent.findViewById(R.id.qsb_divider)); 8 // final ImageView dockDivider = (ImageView) (parent.findViewById(R.id.dock_divider)); 9 final View scrollIndicator = getScrollingIndicator(); 10 11 cancelScrollingIndicatorAnimations(); 12 //if (qsbDivider != null) qsbDivider.setAlpha(reducedFade); 13 //if (dockDivider != null) dockDivider.setAlpha(reducedFade); 14 scrollIndicator.setAlpha(1 - fade); 15 }
也跟我一起屏蔽它們就可以了,這樣煩人的豎線就不會出現了,你也會做到和我在一開始展示的那樣的效果