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列表:

(PS:新建的QQ群,有興趣可以加入一起討論:Android群:322599434)

 

 

1、AppsCustomizePagedView關系

  首先看看Launcher是如何獲取系統里面所有的Widget信息,這一部分都在AppsCustomizePagedView類里面,AppsCustomizePagedView類是同時管理顯示Widget和所有應用列表。這兩者都是這個類負責顯示,看名字我們可以看到一個很熟悉的名字PagedView類,這個類前面我已經分析過,是一個十分重要的積累,繼承於ViewGroup。主界面的WorkSpace也是繼承於PagedView,PagedView主要是實現了頁面滑動功能。AppsCustomizePagedView的基類同樣是PagedView,下面看看他們的繼承關系:

  從上面的繼承關系可以看到,AppsCustomizePagedView也是一個GroupView,主要就是用來顯示其他view,只是多了頁面滑動和拖曳功能。其實這個繼承關系跟WorkSpace是基本一樣,只是中間的類有點不一樣。不了解的朋友,可以看我以前WorkSpace的分析文章。

 

2、Widgets信息收集

下面我們看看AppsCustomizePagedView里面如何統計系統里面Widget的信息。所有的Widget信息會最后保存到一個隊列里面:

 
         
//Edited by mythou
//http://www.cnblogs.com/mythou/
private ArrayList<Object> mWidgets;  //widget資源

下面我們看看,如何統計收集信息

//Edited by mythou
//http://www.cnblogs.com/mythou/
  public void updatePackages() {
        //清空WIdget列表
        boolean wasEmpty = mWidgets.isEmpty();
        mWidgets.clear();
     //這里獲取的是Widget信息 List
<AppWidgetProviderInfo> widgets = AppWidgetManager.getInstance( mLauncher).getInstalledProviders(); Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
    //獲取所有的快捷方式,需要說明的是快捷方式同樣顯示在Widget里面 List
<ResolveInfo> shortcuts = mPackageManager.queryIntentActivities( shortcutsIntent, 0);
     //遍歷所有的Widget插件
for (AppWidgetProviderInfo widget : widgets) {
        //判斷插件的最小高寬是否為0,為0不需要顯示
if (widget.minWidth > 0 && widget.minHeight > 0) {
          //添加到隊列 mWidgets.add(widget); }
else { Log.e(LOG_TAG, "Widget " + widget.provider + " has invalid dimensions (" + widget.minWidth + ", " + widget.minHeight + ")"); } }
     //直接添加所有快捷方式 mWidgets.addAll(shortcuts); Collections.sort(mWidgets,
new LauncherModel.WidgetAndShortcutNameComparator( mPackageManager)); updatePageCounts(); if (wasEmpty) { // The next layout pass will trigger data-ready if both widgets and // apps are set, so request // a layout to do this test and invalidate the page data when ready. if (testDataReady()) requestLayout(); } else { cancelAllTasks(); invalidatePageData(); } }

  上面就是如何獲取系統Widget信息的相關代碼,主要是通過AppWidgetManager服務獲取相關信息。需要注意的是,快捷方式也會顯示在Widget列表里面,獲取快捷方式的方法,主要是通過Intent的標記識別。通過PackageManager.queryIntentActivities,可以指定過濾所有含有ACTION_CREATE_SHORTCUT標識的程序,這些作為快捷方式也會被添加到Widget隊列里面。

 

3、Widget信息初始化

  上面說的是如何獲取Widget的相關對象信息,我們可以看到ArrayList里面的類型也是初始化為Object。下面我們看看如何提取Widget里面的信息,然后初始化為View在界面上面顯示。

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

        //計算Widget相關的長寬和邊距,用於后面確定位置
        final ArrayList<Object> items = new ArrayList<Object>();
        int contentWidth = mWidgetSpacingLayout.getContentWidth();
        final int cellWidth = ((contentWidth - mPageLayoutPaddingLeft
                - mPageLayoutPaddingRight - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX);
        int contentHeight = mWidgetSpacingLayout.getContentHeight();
        final int cellHeight = ((contentHeight - mPageLayoutPaddingTop
                - mPageLayoutPaddingBottom - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY);

        // 這里是計算Widget的數目和每頁數目,用於后面計算WIdget的預覽圖
        int offset = page * numItemsPerPage;
        for (int i = offset; i < Math.min(offset + numItemsPerPage,
                mWidgets.size()); ++i) {
            items.add(mWidgets.get(i));
        }

        //獲取Widget信息,填充到PagedViewWidget對象里面
        final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page
                + mNumAppsPages);
        layout.setColumnCount(layout.getCellCountX());
     //遍歷所有widget和快捷方式
for (int i = 0; i < items.size(); ++i) { Object rawInfo = items.get(i); PendingAddItemInfo createItemInfo = null; PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate( R.layout.apps_customize_widget, layout, false);
        //Widget信息
if (rawInfo instanceof AppWidgetProviderInfo) { // Fill in the widget information AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo; createItemInfo = new PendingAddWidgetInfo(info, null, null); int[] cellSpans = mLauncher.getSpanForWidget(info, null); widget.applyFromAppWidgetProviderInfo(info, -1, cellSpans, mHolographicOutlineHelper); widget.setTag(createItemInfo); }
        //快捷方式
        else if (rawInfo instanceof ResolveInfo) { // Fill in the shortcuts information ResolveInfo info = (ResolveInfo) rawInfo; createItemInfo = new PendingAddItemInfo(); createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; createItemInfo.componentName = new ComponentName( info.activityInfo.packageName, info.activityInfo.name); widget.applyFromResolveInfo(mPackageManager, info, mHolographicOutlineHelper); widget.setTag(createItemInfo); } widget.setOnClickListener(this); widget.setOnLongClickListener(this); widget.setOnTouchListener(this); widget.setOnKeyListener(this); //計算每個Widget的位置和布局信息 int ix = i % mWidgetCountX; int iy = i / mWidgetCountX; GridLayout.LayoutParams lp = new GridLayout.LayoutParams( GridLayout.spec(iy, GridLayout.LEFT), GridLayout.spec(ix, GridLayout.TOP)); lp.width = cellWidth; lp.height = cellHeight; lp.setGravity(Gravity.TOP | Gravity.LEFT); if (ix > 0) lp.leftMargin = mWidgetWidthGap; if (iy > 0) lp.topMargin = mWidgetHeightGap; layout.addView(widget, lp); }

  上面是從我們獲取的Widget對象里面提取Widget信息,包括位置,最小長寬和預覽圖。這里分開了Widget和快捷方式,這兩種處理稍有不同,可以根據上面代碼對比。下面以Widget為例,說說如何生成界面顯示的效果。

 

4、Widget預覽圖

  其實界面上我們看到的Widget預覽圖也是一個布局生成的,就是一個LinearLayout,下面我們簡單看看布局文件R.layout.apps_customize_widget:

//Edited by mythou
//http://www.cnblogs.com/mythou/
<com.android.launcher2.PagedViewWidget
    android:background="@drawable/focusable_view_bg"
    android:focusable="true">

    <LinearLayout
        android:orientation="horizontal">
    <!--Widget名稱和占用空間-->
        <TextView 
            android:textSize="20sp" />

        <TextView 
            android:textSize="30sp" />
    </LinearLayout>
 <!-- Widget的預覽圖-->
    <com.android.launcher2.PagedViewWidgetImageView
        android:id="@+id/widget_preview"
        android:scaleType="matrix" />

</com.android.launcher2.PagedViewWidget>

  上面是Widget預覽圖的布局(我這里刪除了很多屬性,只是給個布局示意),主要就是用了兩個TextView和一個ImageView實現,預覽圖的ImageView被重載了,實現了其他功能。根部局的LinearLayout也被重載,加入其他功能。這里不針對這兩個類詳細分析,PagedViewWidget里面實現了較多功能,包括主要的重繪功能。PagedViewWidgetImageView基本沒有做什么事,可以直接當做ImageView使用。

  上面的信息初始化過程,就是加載了這個布局,然后生成對應的對象,然后設置各種信息以及動作監聽器。

//Edited by mythou
//http://www.cnblogs.com/mythou/
PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
                    R.layout.apps_customize_widget, layout, false);

 

5、結語

  從收集系統信息到初始化相關信息到生成對象大概就是這個過程。Widget縮略圖生成過程比較復雜,這個下次再說吧,今天大伙早點休息,七夕快樂!

 

2013-8-13

Edited by 泡泡糖

 

系列文章:

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

Android Launcher分析和修改7——AllApp全部應用列表(AppsCustomizeTabHost)

Android Launcher分析和修改8——AllAPP界面拖拽元素(PagedViewWithDraggableItems)

Android Launcher分析和修改9——Launcher啟動APP流程

Android Launcher分析和修改10——HotSeat深入進階

Android Launcher分析和修改11——自定義分頁指示器(paged_view_indicator)

 

 

Edited by mythou

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3256212.html 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM