- <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
- <!-- 使用screen作为按钮位置标识-->
- <favorite
- launcher:packageName="com.example.naviback"
- launcher:className="com.example.naviback.MainActivity"
- launcher:container="-101"
- launcher:screen="0"
- launcher:x="0"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.csr.dvd"
- launcher:className="com.csr.dvd.LoadDVD"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.apical.apicalradio"
- launcher:className="com.apical.apicalradio.RadioMainActivity"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.csr.BTApp"
- launcher:className="com.csr.BTApp.CSRBluetoothDemoActivity"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
复制代码default_workspace的配置,我在第一篇文章里面已经说过了,不清楚的可以
点击这里 。配置hotseat的属性跟workspace的有点不一样,下面针对不同的属性进行说明:
- launcher:container:需要标识为-101 ,代表是hotseat的默认按钮。
- launcher:screen:代表按钮的位置,0是第一个位置。ALlApp按钮默认是2,所以上面并没有screen为2的标签。
其他的属性跟workspace配置的属性一样,可以参考我写的第一篇文章。
配置完hotseat的默认按钮后,我们需要修改hotseat.xml的配置属性才能正常显示,下面是hotseat.xml的配置,我是使用了竖屏时的hotseat配置。
- <com.android.launcher2.Hotseat
- xmlns: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" <!--设置hotseat的背景 -->
- launcher:cellCountX="5" <!-- 代表hotseat横向有多少个方格(图标) -->
- launcher:cellCountY="1"> <!-- 代码hotseat竖向有多少个方格-->
- <com.android.launcher2.CellLayout <!--实际容纳按钮的容器是CellLayout -->
- android:id="@+id/layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- <!--下面几个属性就是控制5个按钮的显示位置调整,跟我们一般使用控件属性一样 -->
- android:paddingTop="3dp"
- android:paddingBottom="3dp"
- android:paddingLeft="150dp"
- android:paddingRight="@dimen/button_bar_height_bottom_padding"
- <!-- hotseat里面按钮的大小以及两个按钮之间的间距 -->
- 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>
复制代码上面的属性,有几个我们是需要留意,因为这是直接关系我们hotseat的显示效果。上面我已经给出了一些关键属性大部分跟我们使用一般控件是一样的,其他的launcher:XXX就是launcher自己定义的属性。上面已经给出注释。需要注意的是launcher:cellCountX和launcher:cellCountY两个属性,这个跟横向竖向的hotseat有关。另外就是从中我们也可以看到其实hotseat可以定义多行多列。因为hotseat里面其实是包含了一个CellLayout,跟workspace一样。 除了设置Hotseat的属性外,我们还需要设置workspace的属性,以为hotseat占用了一部分的空间,所以workspace就需要腾出一部分空间处理。例如原来你的workspace没有加入hotseat前是5*3设置,如果需要加入hotseat,你的workspace只能修改为5*2的配置,你需要在竖向空间流出一行的空间给hotseat使用。
2、Hotseat构造函数到这里基本上配置已经设置好。不过显示出来的效果并不是我们想象的结果,因为Hotseat内部对横向和竖向屏幕做了处理,我们需要做些修改。Launcher里面有专门管理Hotseat的类:Hotseat.java 。下面我们看看Hotseat.java的构造:
- 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;
-
- //设置成竖屏,使用竖屏时候的hotseat
- mIsLandscape = false;
- }
复制代码注意这里有一个大屏幕还是小屏幕的判断,这个是用来判断属于平板系统还是一般的手机系统。因为我系统是只会在横屏时使用,所以我直接设置成mIsLandscape为小屏幕,因为Hotseat里面很多获取熟悉都是区分大小屏幕。小屏幕的时候,我们使用竖向配置hotseat就可以得到相当于手机系统的hotseat效果,hotseat会显示在屏幕底下。基本上修改上面几个地方,就可以在平板屏幕底下显示hotseat。下面我们分析一下Hotseat是如何实现的。
3、Hotseat加载数据Hotseat加载数据可以分为两部分,AllApp按钮和其他默认按钮。下面我们先看看其他默认按钮是如何加载的:默认按钮加载跟workspace的默认数据加载一样,都是在LauncherModel加载。Hotseat和workspace的app类型加载方式一样,
- private void loadWorkspace()
- {
- //........
- switch (container)
- {
- case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
- sWorkspaceItems.add(info);
- break;
- //........
- }
复制代码上面是上一篇我们分析Launcher加载初始化数据的部分代码,我们可以看到,Hotseat的数据加载跟workspace的一般APP快捷方式加载是一样的,而且他们共用一个队列保存数据。具体数据加载过程分析可以查看我上一篇文章。
4、Hotseat绑定数据 hotseat绑定数据跟workspace流程基本一样,下面是hotseat开始绑定时,调用了Hotseat自身的方法清空数据。
- public void startBinding()
- {
- //..........
- // 清空Hotseat的数据
- if (mHotseat != null)
- {
- mHotseat.resetLayout();
- }
- }
复制代码上面配置文件分析的时候,我们也说了Hotseat里面其实也是一个CellLayout负责管理内部的元素,下面我们看看它如何绑定数据到CellLayout。在workspace.java类里面的addInScreen()方法实现。
- void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY,
- boolean insert) {
- //...........
- //创建CellLayout,用于添加Hotseat的对象。
- final CellLayout layout;
- if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- layout = mLauncher.getHotseat().getLayout();
- child.setOnKeyListener(null);
- // Hide folder title in the hotseat
- if (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关键的添加代码,其他一些相关的内容,可以查看源码。
5、Hotseat类Hotseat类里面其实东西不多,主要就是我们上面说的构造函数,另外还有下面的设置AllAPP按钮的方法。
- void resetLayout() {
- //清空原来的内容
- mContent.removeAllViewsInLayout();
- //添加AllAPP按钮,也是一个BubbleTextView对象
- Context context = getContext();
- LayoutInflater inflater = LayoutInflater.from(context);
- BubbleTextView allAppsButton = (BubbleTextView)
- inflater.inflate(R.layout.application, mContent, false);
- //加载AllAPP按钮的图标,这里使用了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按钮触摸和点击响应,回调Launcher的功能
- allAppsButton.setOnTouchListener(new View.OnTouchListener()
- {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (mLauncher != null &&
- (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
- mLauncher.onTouchDownAllAppsButton(v);
- }
- return false;
- }
- });
- //AllAPP按钮点击响应的方法,点击的处理在Launcher类里面
- allAppsButton.setOnClickListener(new View.OnClickListener()
- {
- @Override
- public void onClick(android.view.View v) {
- if (mLauncher != null) {
- mLauncher.onClickAllAppsButton(v);
- }
- }
- });
- //这里会判断是小屏幕还是大屏幕,决定AllAPP按钮的位置
- int x = getCellXFromOrder(sAllAppsButtonRank);
- int y = getCellYFromOrder(sAllAppsButtonRank);
- Log.d("Mythou_Launcher", "Hotseat------>x="+x+" y="+y);
- //Hotseat中清空了装载的内容,然后重新加载allAppsButton到CellLayout mythou
- mContent.addViewToCellLayout(allAppsButton, -1, 0, new CellLayout.LayoutParams(x,y,1,1),
- true);
- }
复制代码Hotseat里面其他几个简单方法,基本上都是获取一些属性,这里就不详细分析。
6、总结- Hotseat其实也是一个CellLayout负责管理里面的所有数据。
- 大部分配置可以通过XML配置文件修改得到。
- 加载和绑定数据和workspace基本是一致的。
今天就写到这里,有关CellLayout的分析,下一篇文章会讲述。