Android之Launcher分析和修改5——HotSeat分析
今天主要是分析一下Launcher里面的快捷方式導(dǎo)航條——HotSeat,一般我們使用手機(jī)底下都會(huì)有這個(gè)導(dǎo)航條,但是如果4.0的Launcher放到平板電腦里面運(yùn)行,默認(rèn)是沒有HotSeat的,剛好我這里的運(yùn)行環(huán)境類似平板,系統(tǒng)默認(rèn)把HotSeat去掉了。辦法,只能自己想辦法把它弄出來,所以今天主要是分析如何在你Launcher上添加HotSeat以及分析HotSeat實(shí)現(xiàn)。
Hotseat配置是通過配置文件控制的,一般來說,你需不需要Hotseat只要在配件文件里面寫一下就OK,不過Hotseat有一個(gè)比較麻煩的地方,就是需要注意橫屏還是豎屏。默認(rèn)豎屏的時(shí)候,Hotseat是屏幕底下的,橫屏的時(shí)候,在屏幕右邊。不知道google當(dāng)時(shí)為啥要這樣設(shè)計(jì),可能是為了橫屏的時(shí)候,不占用本來就不多的豎向的空間吧。不過這個(gè)設(shè)計(jì)對于一些橫屏的平板電腦或者移動(dòng)設(shè)備,用戶體驗(yàn)實(shí)在不太好。
?
1、Hotseat配置文件
下面我們看看Hotseat的配置文件,Hotseat是屬于workspace的,所以需要在workspace配置文件里面配置,打開launcher.xml就可以看到hotseat的配置,這個(gè)并不是所有l(wèi)auncher.xml文件都有hotseat屬性。例如:layout-sw600dp文件夾下的launcher.xml就是默認(rèn)沒有hotseat配置,這個(gè)使用在大屏幕,平板之類的設(shè)置上。而我的設(shè)備剛好是使用這個(gè)配置。
所以把hotseat加到layout-sw600dp下的launcher.xml配置文件:
//Edited by mythou //http://www.cnblogs.com/mythou/<!-- WorkSpace最下面的五個(gè)快捷位置 mythou--><include layout="@layout/hotseat"android:id="@+id/hotseat"android:layout_width="match_parent"android:layout_height="@dimen/button_bar_height_plus_padding"android:layout_gravity="bottom" />
注意,我這里是使用了豎屏?xí)r的hotseat配置,因?yàn)槲蚁M鹔otseat是放到屏幕下方。所以android:layout_gravity=
"bottom"也是配置為bottom。hotseat默認(rèn)是有5個(gè)按鈕,其中中間一個(gè)是進(jìn)入AllApp列表的按鈕,這個(gè)是程序里面設(shè)置
(下面會(huì)說到)。其他的默認(rèn)按鈕需要在default_workspace.xml里面配置。
//Edited by mythou //http://www.cnblogs.com/mythou/<!-- Hotseat (We use the screen as the position of the item in the hotseat) --><!-- 使用screen作為按鈕位置標(biāo)識(shí)--><favoritelauncher:packageName="com.example.naviback"launcher:className="com.example.naviback.MainActivity"launcher:container="-101"launcher:screen="0"launcher:x="0"launcher:y="0" /><favoritelauncher:packageName="com.csr.dvd"launcher:className="com.csr.dvd.LoadDVD"launcher:container="-101"launcher:screen="1"launcher:x="1"launcher:y="0" /><favoritelauncher:packageName="com.apical.apicalradio"launcher:className="com.apical.apicalradio.RadioMainActivity"launcher:container="-101"launcher:screen="3"launcher:x="3"launcher:y="0" /><favoritelauncher:packageName="com.csr.BTApp"launcher:className="com.csr.BTApp.CSRBluetoothDemoActivity"launcher:container="-101"launcher:screen="4"launcher:x="4"launcher:y="0" />
default_workspace的配置,我在第一篇文章里面已經(jīng)說過了,不清楚的可以點(diǎn)擊這里?。配置hotseat的屬性跟workspace的有點(diǎn)不一樣,下面針對不同的屬性進(jìn)行說明:
- launcher:container:需要標(biāo)識(shí)為-101 ,代表是hotseat的默認(rèn)按鈕。
- launcher:screen:代表按鈕的位置,0是第一個(gè)位置。ALlApp按鈕默認(rèn)是2,所以上面并沒有screen為2的標(biāo)簽。
配置完hotseat的默認(rèn)按鈕后,我們需要修改hotseat.xml的配置屬性才能正常顯示,下面是hotseat.xml的配置,
我是使用了豎屏?xí)r的hotseat配置。
//Edited by mythou //http://www.cnblogs.com/mythou/ <com.android.launcher2.Hotseatxmlns:android="http://schemas.android.com/apk/res/android"xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"android:background="@drawable/hotseat_bg_panel" <!--設(shè)置hotseat的背景 --> launcher:cellCountX="5" <!-- 代表hotseat橫向有多少個(gè)方格(圖標(biāo)) -->launcher:cellCountY="1"> <!-- 代碼hotseat豎向有多少個(gè)方格--><com.android.launcher2.CellLayout <!--實(shí)際容納按鈕的容器是CellLayout -->android:id="@+id/layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"<!--下面幾個(gè)屬性就是控制5個(gè)按鈕的顯示位置調(diào)整,跟我們一般使用控件屬性一樣 -->android:paddingTop="3dp"android:paddingBottom="3dp"android:paddingLeft="150dp"android:paddingRight="@dimen/button_bar_height_bottom_padding"<!-- hotseat里面按鈕的大小以及兩個(gè)按鈕之間的間距 -->launcher:cellWidth="106dip"launcher:cellHeight="106dip"launcher:widthGap="25dp"launcher:heightGap="@dimen/hotseat_height_gap"launcher:maxGap="@dimen/workspace_max_gap" /> </com.android.launcher2.Hotseat>上面的屬性,有幾個(gè)我們是需要留意,因?yàn)檫@是直接關(guān)系我們hotseat的顯示效果。上面我已經(jīng)給出了一些關(guān)鍵屬性大部分跟我們使用一般控件是一樣的,其他的launcher:XXX就是launcher自己定義的屬性。上面已經(jīng)給出注釋。需要注意的是launcher:cellCountX和launcher:cellCountY兩個(gè)屬性,這個(gè)跟橫向豎向的hotseat有關(guān)。另外就是從中我們也可以看到其實(shí)hotseat可以定義多行多列。因?yàn)閔otseat里面其實(shí)是包含了一個(gè)CellLayout,跟workspace一樣。
除了設(shè)置Hotseat的屬性外,我們還需要設(shè)置workspace的屬性,以為hotseat占用了一部分的空間,所以workspace就需要騰出一部分空間處理。例如原來你的workspace沒有加入hotseat前是5*3設(shè)置,如果需要加入hotseat,你的workspace只能修改為5*2的配置,你需要在豎向空間流出一行的空間給hotseat使用。
?
2、Hotseat構(gòu)造函數(shù)
到這里基本上配置已經(jīng)設(shè)置好。不過顯示出來的效果并不是我們想象的結(jié)果,因?yàn)镠otseat內(nèi)部對橫向和豎向屏幕做了處理,我們需要做些修改。Launcher里面有專門管理Hotseat的類:Hotseat.java 。
下面我們看看Hotseat.java的構(gòu)造:
//Edited by mythou //http://www.cnblogs.com/mythou/public Hotseat(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.Hotseat, defStyle, 0);mCellCountX = a.getInt(R.styleable.Hotseat_cellCountX, -1);mCellCountY = a.getInt(R.styleable.Hotseat_cellCountY, -1);mIsLandscape = context.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_LANDSCAPE;//設(shè)置成豎屏,使用豎屏?xí)r候的hotseatmIsLandscape = false;}注意這里有一個(gè)大屏幕還是小屏幕的判斷,這個(gè)是用來判斷屬于平板系統(tǒng)還是一般的手機(jī)系統(tǒng)。因?yàn)槲蚁到y(tǒng)是只會(huì)在橫屏?xí)r使用,
所以我直接設(shè)置成mIsLandscape為小屏幕,因?yàn)镠otseat里面很多獲取熟悉都是區(qū)分大小屏幕。小屏幕的時(shí)候,我們使用豎向
配置hotseat就可以得到相當(dāng)于手機(jī)系統(tǒng)的hotseat效果,hotseat會(huì)顯示在屏幕底下。
基本上修改上面幾個(gè)地方,就可以在平板屏幕底下顯示hotseat。下面我們分析一下Hotseat是如何實(shí)現(xiàn)的。
?
3、Hotseat加載數(shù)據(jù)
Hotseat加載數(shù)據(jù)可以分為兩部分,AllApp按鈕和其他默認(rèn)按鈕。下面我們先看看其他默認(rèn)按鈕是如何加載的:
默認(rèn)按鈕加載跟workspace的默認(rèn)數(shù)據(jù)加載一樣,都是在LauncherModel加載。
Hotseat和workspace的app類型加載方式一樣,
//Edited by mythou //http://www.cnblogs.com/mythou/ private void loadWorkspace() {//........switch (container) { case LauncherSettings.Favorites.CONTAINER_DESKTOP: case LauncherSettings.Favorites.CONTAINER_HOTSEAT: sWorkspaceItems.add(info); break; //........ }
上面是上一篇我們分析Launcher加載初始化數(shù)據(jù)的部分代碼,我們可以看到,Hotseat的數(shù)據(jù)加載跟workspace的一般APP快捷方式加載是一樣的,而且他們共用一個(gè)隊(duì)列保存數(shù)據(jù)。具體數(shù)據(jù)加載過程分析可以查看我上一篇文章。
?
4、Hotseat綁定數(shù)據(jù)
?hotseat綁定數(shù)據(jù)跟workspace流程基本一樣,下面是hotseat開始綁定時(shí),調(diào)用了Hotseat自身的方法清空數(shù)據(jù)。
public void startBinding() { //..........// 清空Hotseat的數(shù)據(jù)if (mHotseat != null) { mHotseat.resetLayout(); } }
上面配置文件分析的時(shí)候,我們也說了Hotseat里面其實(shí)也是一個(gè)CellLayout負(fù)責(zé)管理內(nèi)部的元素,下面我們看看它如何綁定數(shù)據(jù)
到CellLayout。在workspace.java類里面的addInScreen()方法實(shí)現(xiàn)。
//Edited by mythou //http://www.cnblogs.com/mythou/void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY,boolean insert) {//...........//創(chuàng)建CellLayout,用于添加Hotseat的對象。final CellLayout layout;if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {layout = mLauncher.getHotseat().getLayout();child.setOnKeyListener(null);// Hide folder title in the hotseatif (child instanceof FolderIcon) {((FolderIcon) child).setTextVisible(false);}if (screen < 0) {screen = mLauncher.getHotseat().getOrderInHotseat(x, y);} else {// Note: We do this to ensure that the hotseat is always laid out in the orientation// of the hotseat in order regardless of which orientation they were added//獲取child的位置,返回true添加成功,false失敗 x = mLauncher.getHotseat().getCellXFromOrder(screen);y = mLauncher.getHotseat().getCellYFromOrder(screen);}} else {//如果Hotseat里面有Folder,隱藏文件夾名字if (child instanceof FolderIcon) {((FolderIcon) child).setTextVisible(true);}layout = (CellLayout) getChildAt(screen);child.setOnKeyListener(new IconKeyEventListener());}//.........}這里只給出Hotseat關(guān)鍵的添加代碼,其他一些相關(guān)的內(nèi)容,可以查看源碼。
?
5、Hotseat類
Hotseat類里面其實(shí)東西不多,主要就是我們上面說的構(gòu)造函數(shù),另外還有下面的設(shè)置AllAPP按鈕的方法。
//Edited by mythou //http://www.cnblogs.com/mythou/ void resetLayout() {//清空原來的內(nèi)容mContent.removeAllViewsInLayout();//添加AllAPP按鈕,也是一個(gè)BubbleTextView對象Context context = getContext();LayoutInflater inflater = LayoutInflater.from(context);BubbleTextView allAppsButton = (BubbleTextView)inflater.inflate(R.layout.application, mContent, false);//加載AllAPP按鈕的圖標(biāo),這里使用了selector作為按鈕配置allAppsButton.setCompoundDrawablesWithIntrinsicBounds(null,context.getResources().getDrawable(R.drawable.all_apps_button_icon), null, null);// allAppsButton.setText(context.getString(R.string.all_apps_button_label));allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));//allapp按鈕觸摸和點(diǎn)擊響應(yīng),回調(diào)Launcher的功能allAppsButton.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if (mLauncher != null &&(event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {mLauncher.onTouchDownAllAppsButton(v);}return false;}});//AllAPP按鈕點(diǎn)擊響應(yīng)的方法,點(diǎn)擊的處理在Launcher類里面allAppsButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(android.view.View v) {if (mLauncher != null) {mLauncher.onClickAllAppsButton(v);}}});//這里會(huì)判斷是小屏幕還是大屏幕,決定AllAPP按鈕的位置int x = getCellXFromOrder(sAllAppsButtonRank);int y = getCellYFromOrder(sAllAppsButtonRank);Log.d("Mythou_Launcher", "Hotseat------>x="+x+" y="+y);//Hotseat中清空了裝載的內(nèi)容,然后重新加載allAppsButton到CellLayout mythoumContent.addViewToCellLayout(allAppsButton, -1, 0, new CellLayout.LayoutParams(x,y,1,1),true);} 復(fù)制代碼Hotseat里面其他幾個(gè)簡單方法,基本上都是獲取一些屬性,這里就不詳細(xì)分析。
6、總結(jié)
- Hotseat其實(shí)也是一個(gè)CellLayout負(fù)責(zé)管理里面的所有數(shù)據(jù)。
- 大部分配置可以通過XML配置文件修改得到。
- 加載和綁定數(shù)據(jù)和workspace基本是一致的。
今天就寫到這里,有關(guān)CellLayout的分析,下一篇文章會(huì)講述。
總結(jié)
以上是生活随笔為你收集整理的Android之Launcher分析和修改5——HotSeat分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android之Launcher分析和修
- 下一篇: Android之Android stud