• launcher in android


    http://blog.csdn.net/liangshengyang/article/details/5905351

    Laucher的UI组成

    UI组件属性在layout-port/launcher.xml中定义,主要有Workspace和SlidingDrawer两大部分组成,盛放这两者的容器就是DragLayer。

    1. <com.android.launcher.DragLayer  
    2.     xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"  
    4.   
    5.     android:id="@+id/drag_layer"  
    6.     android:layout_width="fill_parent"  
    7.     android:layout_height="fill_parent">  
    8.   
    9.     <!-- The workspace contains 3 screens of cells -->  
    10.     <com.android.launcher.Workspace  
    11.         android:id="@+id/workspace"  
    12.         android:layout_width="fill_parent"  
    13.         android:layout_height="fill_parent"  
    14.   
    15.         launcher:defaultScreen="1">  
    16.   
    17.         <include android:id="@+id/cell1" layout="@layout/workspace_screen" />  
    18.         <include android:id="@+id/cell2" layout="@layout/workspace_screen" />  
    19.         <include android:id="@+id/cell3" layout="@layout/workspace_screen" />  
    20.   
    21.     </com.android.launcher.Workspace>  
    22.   
    23.     <SlidingDrawer  
    24.         android:id="@+id/drawer"  
    25.         android:layout_width="fill_parent"  
    26.         android:layout_height="fill_parent"  
    27.   
    28.         android:topOffset="5dip"  
    29.         android:bottomOffset="7dip"  
    30.         android:handle="@+id/all_apps"  
    31.         android:content="@+id/content">  
    32.   
    33.         <com.android.launcher.HandleView  
    34.             android:id="@id/all_apps"  
    35.             android:layout_width="fill_parent"  
    36.             android:layout_height="56dip"  
    37.   
    38.             android:background="@drawable/handle"  
    39.   
    40.             android:focusable="true"  
    41.             android:clickable="true"  
    42.   
    43.             android:scaleType="center"  
    44.             android:src="@drawable/handle_icon"  
    45.   
    46.             launcher:direction="horizontal" />  
    47.   
    48.         <com.android.launcher.AllAppsGridView  
    49.             android:id="@id/content"  
    50.             android:layout_width="fill_parent"  
    51.             android:layout_height="fill_parent"  
    52.   
    53.             launcher:texture="@drawable/pattern_carbon_fiber_dark"  
    54.   
    55.             android:scrollbarStyle="outsideInset"  
    56.             android:drawSelectorOnTop="false"  
    57.             android:listSelector="@drawable/grid_selector"  
    58.   
    59.             android:nextFocusLeft="@id/content"  
    60.             android:nextFocusDown="@id/content"  
    61.             android:nextFocusUp="@id/all_apps"  
    62.             android:nextFocusRight="@id/content"  
    63.   
    64.             android:verticalSpacing="10dip"  
    65.             android:numColumns="4" />  
    66.   
    67.     </SlidingDrawer>  
    68.   
    69.     <com.android.launcher.DeleteZone  
    70.         android:id="@+id/delete_zone"  
    71.         android:layout_width="wrap_content"  
    72.         android:layout_height="49dip"  
    73.   
    74.         android:scaleType="center"  
    75.         android:src="@drawable/ic_delete"  
    76.         android:background="@drawable/delete_zone_selector"  
    77.   
    78.         android:layout_gravity="bottom|center_horizontal"  
    79.         android:visibility="invisible"  
    80.           
    81.         launcher:direction="horizontal" />  
    82.   
    83. </com.android.launcher.DragLayer>  

    Workspace就是启动后进入的桌面,可以左右滑动得到3个(默认值)画面,它可以有背景图片作为墙纸。

     

    SlidingDrawer包括HandleView和AllAppsGridView两部分。在屏幕为竖直时(Portait),在layout-port/launcher.xml文件里定义的高度56dip,宽度则充满充满整个屏幕,其背景图片在文件drawable/handle.xml中指定,见上面的layout文件中的定义。文件drawable/handle.xml:

    1. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
    2.     <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/tray_handle_normal" />  
    3.     <item android:state_pressed="true" android:drawable="@drawable/tray_handle_pressed" />  
    4.     <item android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/tray_handle_selected" />  
    5.     <item android:state_enabled="true" android:drawable="@drawable/tray_handle_normal" />  
    6.     <item android:state_focused="true" android:drawable="@drawable/tray_handle_selected" />  
    7. </selector>  

    对于竖直方式来说则是诸如图片res/drawable-port/tray_handle_normal.png。前景图标源则是在

    drawable/handle_icon.xml(见上面的layout文件),该文件为内容为:

    1. <transition xmlns:android="http://schemas.android.com/apk/res/android">  
    2.     <item android:drawable="@drawable/ic_tray_expand"  />  
    3.     <item android:drawable="@drawable/ic_tray_collapse"  />  
    4. </transition>  

    点击或滑动HandleView中的按钮图标,则可显示AllAppsGridView,它包含了系统中的应用程序。再点击或滑动按钮,则隐藏AllAppsGridView。

    在Launcher的onCreate函数中会调用setupViews来初始化各个View类,初始化布局则是由上面的layout文件中定义。setupViews函数代码如下:

    1. /** 
    2.      * Finds all the views we need and configure them properly. 
    3.      */  
    4.     private void setupViews() {  
    5.         mDragLayer = (DragLayer) findViewById(R.id.drag_layer);  
    6.         final DragLayer dragLayer = mDragLayer;  
    7.   
    8.         mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);  
    9.         final Workspace workspace = mWorkspace;  
    10.   
    11.         mDrawer = (SlidingDrawer) dragLayer.findViewById(R.id.drawer);  
    12.         final SlidingDrawer drawer = mDrawer;  
    13.   
    14.         mAllAppsGrid = (AllAppsGridView) drawer.getContent();  
    15.         final AllAppsGridView grid = mAllAppsGrid;  
    16.   
    17.         final DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);  
    18.   
    19.         mHandleView = (HandleView) drawer.findViewById(R.id.all_apps);  
    20.         mHandleView.setLauncher(this);  
    21.         mHandleIcon = (TransitionDrawable) mHandleView.getDrawable();  
    22.         mHandleIcon.setCrossFadeEnabled(true);  
    23.   
    24.         drawer.lock();  
    25.         final DrawerManager drawerManager = new DrawerManager();  
    26.         drawer.setOnDrawerOpenListener(drawerManager);  
    27.         drawer.setOnDrawerCloseListener(drawerManager);  
    28.         drawer.setOnDrawerScrollListener(drawerManager);  
    29.   
    30.         grid.setTextFilterEnabled(false);  
    31.         grid.setDragger(dragLayer);  
    32.         grid.setLauncher(this);  
    33.   
    34.         workspace.setOnLongClickListener(this);  
    35.         workspace.setDragger(dragLayer);  
    36.         workspace.setLauncher(this);  
    37.         loadWallpaper();  
    38.   
    39.         deleteZone.setLauncher(this);  
    40.         deleteZone.setDragController(dragLayer);  
    41.         deleteZone.setHandle(mHandleView);  
    42.   
    43.         dragLayer.setIgnoredDropTarget(grid);  
    44.         dragLayer.setDragScoller(workspace);  
    45.         dragLayer.setDragListener(deleteZone);  
    46.     }  

    其中DeleteZone用于:当长按workspace中的图标时会进入拖拽功能,可以将它们托到HandleView中,将它们从workspace中删除。

    App的装载

    在onCreate函数中,有如下这2行代码,用于装载应用程序信息,

    1. if (!mRestoring) {  
    2.             startLoaders();  
    3.         }  

    startLoaders会调用LauncherModel的loadApplications函数:

    1. private void startLoaders() {  
    2.     boolean loadApplications = sModel.loadApplications(true, this, mLocaleChanged);  
    3.     sModel.loadUserItems(!mLocaleChanged, this, mLocaleChanged, loadApplications);  
    4.   
    5.     mRestoring = false;  
    6. }  

    第一行装载应用程序包,第二行的函数装载workspace中用户自定义添加到ShortCut,LiveFolder,WidgetApp等。

    在loadApplications中,需要注意2个地方,一是创建ApplicationsAdapter,它将应用程序数组列表ArrayList<ApplicationInfo> mApplications和View关联起来。二是继续调用函数startApplicationsLoaderLocked:

    1. /** 
    2.      * Loads the list of installed applications in mApplications. 
    3.      * 
    4.      * @return true if the applications loader must be started 
    5.      *         (see startApplicationsLoader()), false otherwise. 
    6.      */  
    7.     synchronized boolean loadApplications(boolean isLaunching, Launcher launcher,  
    8.             boolean localeChanged) {  
    9.   
    10.         if (DEBUG_LOADERS) d(LOG_TAG, "load applications");  
    11.   
    12.         if (isLaunching && mApplicationsLoaded && !localeChanged) {  
    13.             mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications);  
    14.             if (DEBUG_LOADERS) d(LOG_TAG, "  --> applications loaded, return");  
    15.             return false;  
    16.         }  
    17.   
    18.         stopAndWaitForApplicationsLoader();  
    19.   
    20.         if (localeChanged) {  
    21.             dropApplicationCache();  
    22.         }  
    23.   
    24.         if (mApplicationsAdapter == null || isLaunching || localeChanged) {  
    25.             mApplications = new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);  
    26.             mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications);  
    27.         }  
    28.   
    29.         mApplicationsLoaded = false;  
    30.   
    31.         if (!isLaunching) {  
    32.             startApplicationsLoaderLocked(launcher, false);  
    33.             return false;  
    34.         }  
    35.   
    36.         return true;  
    37.     }  

    再来看看startApplicationsLoaderLocked,它实际上启动一个线程去装载应用程序信息:

    1. private void startApplicationsLoaderLocked(Launcher launcher, boolean isLaunching) {  
    2.      if (DEBUG_LOADERS) d(LOG_TAG, "  --> starting applications loader");  
    3.   
    4.      stopAndWaitForApplicationsLoader();  
    5.   
    6.      mApplicationsLoader = new ApplicationsLoader(launcher, isLaunching);  
    7.      mApplicationsLoaderThread = new Thread(mApplicationsLoader, "Applications Loader");  
    8.      mApplicationsLoaderThread.start();  
    9.  }  

    它创建一个线程执行体Runnable对象mApplicationsLoader,然后在调用mApplicationsLoaderThread.start()时会执行ApplicationsLoader. run():

    1. public void run() {  
    2.             if (DEBUG_LOADERS) d(LOG_TAG, "  ----> running applications loader (" + mId + ")");  
    3.   
    4.             // Elevate priority when Home launches for the first time to avoid  
    5.             // starving at boot time. Staring at a blank home is not cool.  
    6.             android.os.Process.setThreadPriority(mIsLaunching ? Process.THREAD_PRIORITY_DEFAULT :  
    7.                     Process.THREAD_PRIORITY_BACKGROUND);  
    8.   
    9.             final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);  
    10.             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
    11.   
    12.             final Launcher launcher = mLauncher.get();  
    13.             final PackageManager manager = launcher.getPackageManager();  
    14.             final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);  
    15.   
    16.             if (apps != null && !mStopped) {  
    17.                 final int count = apps.size();  
    18.                 // Can be set to null on the UI thread by the unbind() method  
    19.                 // Do not access without checking for null first  
    20.                 final ApplicationsAdapter applicationList = mApplicationsAdapter;  
    21.   
    22.                 ChangeNotifier action = new ChangeNotifier(applicationList, true);  
    23.                 final HashMap<ComponentName, ApplicationInfo> appInfoCache = mAppInfoCache;  
    24.   
    25.                 for (int i = 0; i < count && !mStopped; i++) {  
    26.                     ResolveInfo info = apps.get(i);  
    27.                     ApplicationInfo application =  
    28.                         makeAndCacheApplicationInfo(manager, appInfoCache, info, launcher);  
    29.   
    30.                     if (action.add(application) && !mStopped) {  
    31.                         launcher.runOnUiThread(action);  
    32.                         action = new ChangeNotifier(applicationList, false);  
    33.                     }  
    34.                 }  
    35.   
    36.                 launcher.runOnUiThread(action);  
    37.             }  
    38.   
    39.             if (!mStopped) {  
    40.                 mApplicationsLoaded = true;  
    41.             } else {  
    42.                 if (DEBUG_LOADERS) d(LOG_TAG, "  ----> applications loader stopped (" + mId + ")");                                  
    43.             }  
    44.             mRunning = false;  
    45.         }  
    46.     }  

    在该线程中,它使用PackageManager获取安装的应用程序。

    在装载完workspace和AllGridView中的各项后,onDesktopItemsLoaded将被调用,它会绑定桌面的Shortcut及appWidgets:

    1. void onDesktopItemsLoaded(ArrayList<ItemInfo> shortcuts,  
    2.           ArrayList<LauncherAppWidgetInfo> appWidgets) {  
    3.       if (mDestroyed) {  
    4.           if (LauncherModel.DEBUG_LOADERS) {  
    5.               d(LauncherModel.LOG_TAG, "  ------> destroyed, ignoring desktop items");  
    6.           }  
    7.           return;  
    8.       }  
    9.       bindDesktopItems(shortcuts, appWidgets);  
    10.   }  

    绑定过程

    绑定过程包括ApplicationAdapter(即ArrayAapter的子类)与AllGridView的绑定,实现数据到View的显示。

    1. private void bindDesktopItems(ArrayList<ItemInfo> shortcuts,  
    2.         ArrayList<LauncherAppWidgetInfo> appWidgets) {  
    3.   
    4.     final ApplicationsAdapter drawerAdapter = sModel.getApplicationsAdapter();  
    5.     if (shortcuts == null || appWidgets == null || drawerAdapter == null) {  
    6.         if (LauncherModel.DEBUG_LOADERS) d(LauncherModel.LOG_TAG, "  ------> a source is null");              
    7.         return;  
    8.     }  
    9.   
    10.   
    11.   
    12.  mBinder = new DesktopBinder(this, shortcuts, appWidgets, drawerAdapter);  
    13.     mBinder.startBindingItems();  
    14. }  

    DesktopBinder的构造函数如下,指定了Adapter,实现了数据到view的绑定:

    1.         DesktopBinder(Launcher launcher, ArrayList<ItemInfo> shortcuts,  
    2.                 ArrayList<LauncherAppWidgetInfo> appWidgets,  
    3.                 ApplicationsAdapter drawerAdapter) {  
    4.   
    5.             mLauncher = new   
    6. WeakReference<Launcher>(launcher);  
    7.             mShortcuts = shortcuts;  
    8.             mDrawerAdapter = drawerAdapter;  
    9. ...  

    在函数bindDrawer 中为view指定了adapter:

    1. private void bindDrawer(Launcher.DesktopBinder binder,  
    2.         ApplicationsAdapter drawerAdapter) {  
    3.     mAllAppsGrid.setAdapter(drawerAdapter);  
    4.     binder.startBindingAppWidgetsWhenIdle();  
    5. }  

    其它

    LauncherModel提供了添加/删除/更新应用程序包的功能 。

    Launcher还提供了对ShortCut 、AppWidget、LiveFolder和搜索框等的管理功能,墙纸管理功能。默认的墙纸也是存放在该程序包的资源中。

  • 相关阅读:
    forms组件、cookie与session
    choices参数、MTV与MVC模型、Ajax、序列化组件、sweetalert搭建页面、自定义分页器
    Django 常用字段,数据库查询优化 only与defer
    django配置代码
    django 模板层、模型层
    Django 请求生命周期、路由层
    centos6.8安装httpd后无法访问
    初次认识dedecms和帝国cms内容管理系统
    遇到一个json解码失败的问题
    关于apache配置映射端口
  • 原文地址:https://www.cnblogs.com/greywolf/p/2831239.html
Copyright © 2020-2023  润新知