Android Launcher分析和修改12——Widget列表信息收集

很久没写Launcher分析的文章,最近实在太忙。今天七夕本来是想陪女朋友逛街 ,碰巧打台风呆在家里,就继续写一篇文章。今天主要是讲一下Launcher里面的Widget列表,这方面信息比较多,今天重点讲一下Widget信息收集和Launcher是如何显示Widget。这是这个系列第12篇文章,可是有关Launcher的分析感觉还有很多东西要写。

  Widget列表是Android4.0以后才有的一种新特性,主要是可以直接查看Widget的缩略图,方便用户使用。而且Widget列表放到了AllApp里面,用一个TabHost管理。有关AllApp的TabHost切换,可以参考我前面的文章:AllApp全部应用列表(AppsCustomizeTabHost) 。Widget列表就是在AllApp列表后面。下面是Launcher4.0 的Widget列表:

13230541-350cce398f6b4d0894098e19bfa01109.jpg 

1、AppsCustomizePagedView关系

  首先看看Launcher是如何获取系统里面所有的Widget信息,这一部分都在AppsCustomizePagedView类里面,AppsCustomizePagedView类是同时管理显示Widget和所有应用列表。这两者都是这个类负责显示,看名字我们可以看到一个很熟悉的名字PagedView类,这个类前面我已经分析过,是一个十分重要的积累,继承于ViewGroup。主界面的WorkSpace也是继承于PagedView,PagedView主要是实现了页面滑动功能。AppsCustomizePagedView的基类同样是PagedView,下面看看他们的继承关系:

13225008-2621bc32952b4013aa76f685878b1ca2.jpg 

  从上面的继承关系可以看到,AppsCustomizePagedView也是一个GroupView,主要就是用来显示其他view,只是多了页面滑动和拖曳功能。其实这个继承关系跟WorkSpace是基本一样,只是中间的类有点不一样。不了解的朋友,可以看我以前WorkSpace的分析文章。

2、Widgets信息收集

下面我们看看AppsCustomizePagedView里面如何统计系统里面Widget的信息。所有的Widget信息会最后保存到一个队列里面:

  1. //Edited by mythou
  2. //http://www.cnblogs.com/mythou/
  3. private ArrayList mWidgets;  //widget资源
复制代码

下面我们看看,如何统计收集信息

  1. //Edited by mythou
  2. //http://www.cnblogs.com/mythou/
  3.   public void updatePackages() {
  4.         //清空WIdget列表
  5.         boolean wasEmpty = mWidgets.isEmpty();
  6.         mWidgets.clear();
  7.      //这里获取的是Widget信息
  8.         List widgets = AppWidgetManager.getInstance(
  9.                 mLauncher).getInstalledProviders();
  10.         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
  11.     //获取所有的快捷方式,需要说明的是快捷方式同样显示在Widget里面
  12.         List shortcuts = mPackageManager.queryIntentActivities(
  13.                 shortcutsIntent, 0);
  14.      //遍历所有的Widget插件
  15.         for (AppWidgetProviderInfo widget : widgets) {
  16.         //判断插件的最小高宽是否为0,为0不需要显示
  17.             if (widget.minWidth > 0 && widget.minHeight > 0) {
  18.           //添加到队列
  19.                 mWidgets.add(widget);
  20.             } else {
  21.                 Log.e(LOG_TAG, "Widget " + widget.provider
  22.                         + " has invalid dimensions (" + widget.minWidth + ", "
  23.                         + widget.minHeight + ")");
  24.             }
  25.         }
  26.      //直接添加所有快捷方式
  27.         mWidgets.addAll(shortcuts);
  28.         Collections.sort(mWidgets,
  29.                 new LauncherModel.WidgetAndShortcutNameComparator(
  30.                         mPackageManager));
  31.         updatePageCounts();

  32.         if (wasEmpty) {
  33.             // The next layout pass will trigger data-ready if both widgets and
  34.             // apps are set, so request
  35.             // a layout to do this test and invalidate the page data when ready.
  36.             if (testDataReady())
  37.                 requestLayout();
  38.         } else {
  39.             cancelAllTasks();
  40.             invalidatePageData();
  41.         }
  42.     }
复制代码

  上面就是如何获取系统Widget信息的相关代码,主要是通过AppWidgetManager服务获取相关信息。需要注意的是,快捷方式也会显示在Widget列表里面,获取快捷方式的方法,主要是通过Intent的标记识别。通过PackageManager.queryIntentActivities,可以指定过滤所有含有ACTION_CREATE_SHORTCUT标识的程序,这些作为快捷方式也会被添加到Widget队列里面。

3、Widget信息初始化

  上面说的是如何获取Widget的相关对象信息,我们可以看到ArrayList里面的类型也是初始化为Object。下面我们看看如何提取Widget里面的信息,然后初始化为View在界面上面显示。

  1. //Edited by mythou
  2. //http://www.cnblogs.com/mythou/
  3. public void syncWidgetPageItems(final int page, final boolean immediate) {
  4.         int numItemsPerPage = mWidgetCountX * mWidgetCountY;

  5.         //计算Widget相关的长宽和边距,用于后面确定位置
  6.         final ArrayList items = new ArrayList();
  7.         int contentWidth = mWidgetSpacingLayout.getContentWidth();
  8.         final int cellWidth = ((contentWidth - mPageLayoutPaddingLeft
  9.                 - mPageLayoutPaddingRight - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX);
  10.         int contentHeight = mWidgetSpacingLayout.getContentHeight();
  11.         final int cellHeight = ((contentHeight - mPageLayoutPaddingTop
  12.                 - mPageLayoutPaddingBottom - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY);

  13.         // 这里是计算Widget的数目和每页数目,用于后面计算WIdget的预览图
  14.         int offset = page * numItemsPerPage;
  15.         for (int i = offset; i < Math.min(offset + numItemsPerPage,
  16.                 mWidgets.size()); ++i) {
  17.             items.add(mWidgets.get(i));
  18.         }

  19.         //获取Widget信息,填充到PagedViewWidget对象里面
  20.         final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page
  21.                 + mNumAppsPages);
  22.         layout.setColumnCount(layout.getCellCountX());
  23.      //遍历所有widget和快捷方式
  24.         for (int i = 0; i < items.size(); ++i) {
  25.             Object rawInfo = items.get(i);
  26.             PendingAddItemInfo createItemInfo = null;
  27.             PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
  28.                     R.layout.apps_customize_widget, layout, false);
  29.         //Widget信息
  30.             if (rawInfo instanceof AppWidgetProviderInfo) {
  31.                 // Fill in the widget information
  32.                 AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
  33.                 createItemInfo = new PendingAddWidgetInfo(info, null, null);
  34.                 int[] cellSpans = mLauncher.getSpanForWidget(info, null);
  35.                 widget.applyFromAppWidgetProviderInfo(info, -1, cellSpans,
  36.                         mHolographicOutlineHelper);
  37.                 widget.setTag(createItemInfo);
  38.             } 
  39.         //快捷方式
  40.         else if (rawInfo instanceof ResolveInfo) {
  41.                 // Fill in the shortcuts information
  42.                 ResolveInfo info = (ResolveInfo) rawInfo;
  43.                 createItemInfo = new PendingAddItemInfo();
  44.                 createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
  45.                 createItemInfo.componentName = new ComponentName(
  46.                         info.activityInfo.packageName, info.activityInfo.name);
  47.                 widget.applyFromResolveInfo(mPackageManager, info,
  48.                         mHolographicOutlineHelper);
  49.                 widget.setTag(createItemInfo);
  50.             }
  51.             widget.setOnClickListener(this);
  52.             widget.setOnLongClickListener(this);
  53.             widget.setOnTouchListener(this);
  54.             widget.setOnKeyListener(this);

  55.             //计算每个Widget的位置和布局信息
  56.             int ix = i % mWidgetCountX;
  57.             int iy = i / mWidgetCountX;
  58.             GridLayout.LayoutParams lp = new GridLayout.LayoutParams(
  59.                     GridLayout.spec(iy, GridLayout.LEFT), GridLayout.spec(ix,
  60.                             GridLayout.TOP));
  61.             lp.width = cellWidth;
  62.             lp.height = cellHeight;
  63.             lp.setGravity(Gravity.TOP | Gravity.LEFT);
  64.             if (ix > 0)
  65.                 lp.leftMargin = mWidgetWidthGap;
  66.             if (iy > 0)
  67.                 lp.topMargin = mWidgetHeightGap;
  68.             layout.addView(widget, lp);
  69.         }
复制代码

  上面是从我们获取的Widget对象里面提取Widget信息,包括位置,最小长宽和预览图。这里分开了Widget和快捷方式,这两种处理稍有不同,可以根据上面代码对比。下面以Widget为例,说说如何生成界面显示的效果。

4、Widget预览图

  其实界面上我们看到的Widget预览图也是一个布局生成的,就是一个LinearLayout,下面我们简单看看布局文件R.layout.apps_customize_widget:

  1. //Edited by mythou
  2. //http://www.cnblogs.com/mythou/
  3. <com.android.launcher2.pagedviewwidget
  4.     android:background="@drawable/focusable_view_bg"
  5.     android:focusable="true">

  6.     <linearlayout
  7.         androidrientation="horizontal">
  8.         
  9.         <textview 
  10.             android:textSize="20sp" />

  11.         <textview 
  12.             android:textSize="30sp" />

  13.     <com.android.launcher2.pagedviewwidgetimageview
  14.         android:id="@+id/widget_preview"
  15.         android:scaleType="matrix" />
复制代码

  上面是Widget预览图的布局(我这里删除了很多属性,只是给个布局示意),主要就是用了两个TextView和一个ImageView实现,预览图的ImageView被重载了,实现了其他功能。根部局的LinearLayout也被重载,加入其他功能。这里不针对这两个类详细分析,PagedViewWidget里面实现了较多功能,包括主要的重绘功能。PagedViewWidgetImageView基本没有做什么事,可以直接当做ImageView使用。

  上面的信息初始化过程,就是加载了这个布局,然后生成对应的对象,然后设置各种信息以及动作监听器。

  1. //Edited by mythou
  2. //http://www.cnblogs.com/mythou/
  3. PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
  4.                     R.layout.apps_customize_widget, layout, false);
复制代码

5、结语

  从收集系统信息到初始化相关信息到生成对象大概就是这个过程。Widget缩略图生成过程比较复杂,这个下次再说吧,今天大伙早点休息,七夕快乐!
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值