android Launcher源码解析01:UI布局详解02——获取应用列表

        本系列文章将开始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源码解析


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值