android Launcher源碼解析01:UI布局詳解02——擷取應用列表

來源:互聯網
上載者:User

        本系列文章將開始android lancher源碼分析,使用的例子是android 2.3中內建的launcher3源碼。其為http://download.csdn.net/detail/xianming01/4383598

       在上一篇文章《android Launcher源碼解析01:UI布局詳解一》中,我們介紹了launcher3中的主題UI布局。這一篇我們將開始介紹其中的某個組成部分。

       今天要介紹的是是擷取應用列表這一部分。

1、布局檔案
       這一部分的介面顯示是這樣的:


      其組成成分為一個應用列表和一個home按鈕。

       在lancher的布局檔案launcher.xml中,關於應用列表的部分為:

<include layout="@layout/all_apps" />  

這裡實際上是包含了all_apps.xml這個布局檔案,其內容為:

<merge xmlns:android="http://schemas.android.com/apk/res/android">    <include layout="@layout/all_apps_2d" /></merge>

其作用是將all_apps_2d.xml這個布局檔案包含進來,其內容為:

<com.android.launcher3.AllApps2D    xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/all_apps_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:padding="2dip"    >    <GridView android:id="@+id/all_apps_2d_grid"        android:tag="all_apps_2d_grid"        android:scrollbars="none"        android:drawSelectorOnTop="false"        android:listSelector="@drawable/grid_selector"        android:verticalSpacing="10dip"        android:numColumns="6"        android:fadingEdgeLength="48dip"        android:cacheColorHint="#FF000000"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_alignParentRight="true"        android:layout_marginRight="@dimen/button_bar_height_portrait"        android:nextFocusRight="@+id/all_apps_2d_home"        android:nextFocusUp="@null"        android:nextFocusLeft="@null"        android:nextFocusDown="@null"        />    <view        class="com.android.launcher3.AllApps2D$HomeButton"        android:id="@+id/all_apps_2d_home"        android:tag="all_apps_2d_home"        android:src="@drawable/home_button"        android:background="#FF000000"        android:layout_alignParentRight="true"        android:layout_centerVertical="true"        android:layout_height="wrap_content"        android:layout_width="@dimen/button_bar_height_portrait"        android:paddingBottom="@dimen/status_bar_height"        android:nextFocusLeft="@+id/all_apps_2d_grid"        android:nextFocusDown="@null"        android:nextFocusUp="@null"        android:nextFocusRight="@null"        /></com.android.launcher3.AllApps2D>

從上面我們可以看出,這一部分的實現是由一個gridview來顯示應用程式列表,而home按鈕則是一個view.

2、實現原理

      在AllApps2D.java這個類中,我們可以看到這一部分的實現。實際上在本人的部落格《android
Launcher基礎知識》中有關於這一部分的簡單形式,有興趣的可以看一下,那個比較簡單.
       在代碼中是如何?的呢?我們來找一下:

mHandleView = (HandleView) findViewById(R.id.all_apps_button);          mHandleView.setLauncher(this);          mHandleView.setOnClickListener(this);          mHandleView.setOnLongClickListener(this); 

再看onclick()方法:在onclick方法中,有一下代碼

else if (v == mHandleView) {              if (isAllAppsVisible()) {                  closeAllApps(true);              } else {                  showAllApps(true);              }  

我們再找一下showAllApps()方法

void showAllApps(boolean animated) {          mAllAppsGrid.zoom(1.0f, animated);            ((View) mAllAppsGrid).setFocusable(true);          ((View) mAllAppsGrid).requestFocus();                    // TODO: fade these two too          mDeleteZone.setVisibility(View.GONE);          mHandleView.setVisibility(View.GONE);          mPreviousView.setVisibility(View.GONE);          mNextView.setVisibility(View.GONE);      hotseatLeft.setVisibility(View.GONE);      hotseatRight.setVisibility(View.GONE);      }  

在上面用到了mAllAppsGrid,我們找一下這個控制項:

private AllAppsView mAllAppsGrid;            mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);          mAllAppsGrid.setLauncher(this);          mAllAppsGrid.setDragController(dragController);          ((View) mAllAppsGrid).setWillNotDraw(false); // We don't want a hole punched in our window.          // Manage focusability manually since this thing is always visible          ((View) mAllAppsGrid).setFocusable(false);  

上面代碼是在Launcher.java中的setupview()方法中定義
all_apps_view是在all_app_2d.xml中定義。
你想找到AllApp2D.java中,可以找到mAllAppsGrid使用的方法,如addApps,removeApps,zoom這幾個方法:

public void addApps(ArrayList<ApplicationInfo> list) {  //        Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());            final int N = list.size();            for (int i=0; i<N; i++) {              final ApplicationInfo item = list.get(i);              int index = Collections.binarySearch(mAllAppsList, item,                      LauncherModel.APP_NAME_COMPARATOR);              if (index < 0) {                  index = -(index+1);              }              mAllAppsList.add(index, item);          }          mAppsAdapter.notifyDataSetChanged();      }        public void removeApps(ArrayList<ApplicationInfo> list) {          final int N = list.size();          for (int i=0; i<N; i++) {              final ApplicationInfo item = list.get(i);              int index = findAppByComponent(mAllAppsList, item);              if (index >= 0) {                  mAllAppsList.remove(index);              } else {                  Log.w(TAG, "couldn't find a match for item \"" + item + "\"");                  // Try to recover.  This should keep us from crashing for now.              }          }          mAppsAdapter.notifyDataSetChanged();      }         public void zoom(float zoom, boolean animate) {  //        Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));          cancelLongPress();            mZoom = zoom;            if (isVisible()) {              getParent().bringChildToFront(this);              setVisibility(View.VISIBLE);              mGrid.setAdapter(mAppsAdapter);              if (animate) {                  startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));              } else {                  onAnimationEnd();              }          } else {              if (animate) {                  startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));              } else {                  onAnimationEnd();              }          }      }  

在zoom()方法裡面有mGrid.setAdapter(mAppsAdapter),在構造方法中,給adapter已經賦值。

public AllApps2D(Context context, AttributeSet attrs) {          super(context, attrs);          setVisibility(View.GONE);          setSoundEffectsEnabled(false);            mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);          mAppsAdapter.setNotifyOnChange(false);      }  

那是如何擷取應用列表的呢?我們再回到Launcher.java中,在loadHotseats()中。由於該函數比較複雜,我們就不全顯示了,只顯示其中比較重要的部分:

PackageManager pm = getPackageManager();  ResolveInfo bestMatch = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);  List<ResolveInfo> allMatches = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);  

這樣就擷取了。下面以一個簡單的例子結束,擷取在sd卡中安裝的程式列表:

private void getSdcardApps(){          mSdcardAppsList.clear();          ActivityManager am = (ActivityManager)mLauncher.getSystemService(Activity.ACTIVITY_SERVICE);          PackageManager pm =mLauncher.getPackageManager();            List<android.content.pm.ApplicationInfo> list = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);          for (android.content.pm.ApplicationInfo appInfo : list) {                  if((appInfo.flags & android.content.pm.ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0){                      for (ApplicationInfo applicationInfo : mAllAppsList) {                          if(appInfo.packageName.equals(applicationInfo.componentName.getPackageName())){                              mSdcardAppsList.add(applicationInfo);                              break;                          }                      }                  }          }          mAppsAdapter = new AppsAdapter(getContext(), mSdcardAppsList);          mAppsAdapter.notifyDataSetChanged();          mGrid.setAdapter(mAppsAdapter);          text.setVisibility(View.VISIBLE);          text.setBackgroundResource(R.drawable.tab_mmenu_b3_normal);      }  

以上就是擷取應用列表的UI布局這一部分的解析。其中還涉及到一些重要的方面沒有解釋,比如在有的手機上可以通過上下滑動來查看app,有些確實通過左右翻頁來查看app,這個是如何?的?這個將在下一篇文章中介紹。

參考資料:

launcher修改--擷取應用列表launcher源碼解析


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.