Launcher介绍总结

2024-03-31 08:48
文章标签 总结 介绍 launcher

本文主要是介绍Launcher介绍总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://blog.csdn.net/ldinvicible/article/details/8488126


一、主要文件和类 

1.Launcher.java:launcher中主要的activity。

 

2.DragLayer.java:launcher layout的根view。DragLayer实际上也是一个抽象的界面,用来处理拖动和对事件进行初步处理然后按情况分发下去,角色是一个controller。它首先用onInterceptTouchEvent(MotionEvent)来拦截所有的touch事件,如果是长按item拖动的话不把事件传下去,直接交由onTouchEvent()处理,这样就可以实现item的移动了,如果不是拖动item的话就把事件传到目标view,交有目标view的事件处理函数做相应处理。如过有要对事件的特殊需求的话可以修改onInterceptTouchEvent(MotionEvent)来实现所需要的功能。

 

3. DragController.java:为Drag定义的一个接口。包含一个接口,两个方法和两个静态常量。接口为DragListener(包含onDragStart(),onDragEnd()两个函数),onDragStart()是在刚开始拖动的时候被调用,onDragEnd()是在拖动完成时被调用。在launcher中典型的应用是DeleteZone,在长按拖动item时调用onDragStart()显示,在拖动结束的时候onDragEnd()隐藏。函数包括startDrag()用于在拖动时传递要拖动的item的信息以及拖动的方式。他有两个常量为DRAG_ACTION_MOVE,DRAG_ACTION_COPY来标识拖动的方式,DRAG_ACTION_MOVE为移动,表示在拖动的时候需要删除原来的item,DRAG_ACTION_COPY为复制型的拖动,表示保留被拖动的item(未使用)。

 

4.LauncherModel.java:辅助的文件。里面有许多封装的对数据库的操作。loadAndBindAllApps加载所有应用程序,loadAndBindWorkspace加载workspace。其他的函数就是对数据库的封装,比如在删除,替换,添加程序的时候做更新数据库和UI的工作。

 

5.Workspace.java:抽象的桌面,继承自ViewGroup,是一个子view。由N个celllaout组成,从cellLayout更高一级的层面上对事件的处理。

 

6.LauncherProvider.java:launcher的数据库,里面存储了桌面的item的信息。在创建数据库的时候会loadFavorites(db)方法,loadFavorites()会解析xml目录下的default_workspace.xml文件,把其中的内容读出来写到数据库中,这样就做到了桌面的预制。

 

7.CellLayout.java:组成workspace的view,继承自viewgroup,既是一个dragSource,又是一个dropTarget,可以将它里面的item拖出去,也可以容纳拖动过来的item。在workspace_screen里面定了一些它的view参数。

 

8.ItemInfo.java:对item的抽象,所有类型item的父类,item包含的属性有id(标识item的id),cellX(在横向位置上的位置,从0开始),cellY(在纵向位置上的位置,从0开始) ,spanX(在横向位置上所占的单位格),spanY(在纵向位置上所占的单位格),screen(在workspace的第几屏,从0开始),itemType(item的类型,有widget,search,application等),container(item所在的)。

 

9.UserFolder.java: 用户创建的文件夹。可以将item拖进文件夹,单击时打开文件夹,长按文件夹上面标题处可以重命名文件夹。

 

10.LiveFolder.java:系统自带的文件夹。从系统中创建出的如联系人的文件夹等。 

 

11.DeleteZone:删除框。在平时是出于隐藏状态,在将item长按拖动的时候会显示出来,如果将item拖动到删除框位置时会删除item。DeleteZone实现了DropTarget和DragListener两个接口。

 

12.LauncherSettings.java:字符串的定义。数据库项的字符串定义,另外在这里定义了container的类型,还有itemType的定义,除此还有一些特殊的widget(如search,clock的定义等)的类型定义。

 

主要布局文件介绍:

packages/apps/Launcher2/res/layout-port/launcher.xml 

总布局文件竖屏,主要显示workspace  HandleView等按键

/packages/res/Launcher2/res/workspase_screen.xml   

cell的数量及显示大小

/packages/res/Launcher2/res/layout/AllAppSpace.xml

显示allapp界面布局(注意不是all_apps_2d.xml

/packages/res/Launcher2/res/xml/default_workspace.xml

显示在workspace上默认的控件位置设置

/packages/res/Launcher2/res/xml/workspace_settings.xml

Workspace界面一些特效设置选项

/packages/res/Launcher2/res/layout/allapp_workspace_screen.xml

All app界面app布局显示

/packages/apps/Launcher2/res/layout-port/all_apps_horizontal.xml

All app界面布局显示(包括指示图标与app布局)

 

 

二、LauncherApplication全局数据初始化过程

LauncherApplication是Application的子类,是整个程序的入口。因此,一些全局信息的初始化和保存工作就放到这里执行。包括屏幕大小,像素密度信息的获取,以及

BroadcastReceiver和ContentObserver的注册都在整个程序的开始就完成。

1、  VMRuntime.getRuntime().setMinimumHeapSize(4 * 1024 * 1024)

设置运行最小堆内存

2、  mIconCache = new IconCache()

实例化图标缓存区的对象

3、  mModel = new LauncherModel()

实例化一个LauncherModel对象,这个类是保存Launcher的内存启动状态,更新Launcher的数据库的作用  

4、  IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);

注册监听,应用package增加,删除,改变的监听。

5、  filter = new IntentFilter() 

注册application是否可用,方向改变的监听

6、 ContentResolver resolver = getContentResolver(),resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URItrue, mFavoritesObserver)。

注册favorites应用程序数据库改变的监听  

7、初始化all app信息

数据库mFavoritesObserver监听内部类

    private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {

        @Override

        public void onChange(boolean selfChange) {

            mModel.startLoader(LauncherApplication.thisfalse);

        }

    };

 

 

三、Launcher.java的onCreate()  所有界面初始化过程

LauncherApplication.onCreate()方法启动完成后,接着开始调用Launcher.java的onCreate()方法之后开始初始化Launcher。

 

可以将Launcher.onCreate()所执行的操作大概分为以下几步:

 

1、  LauncherAppliaction.setLauncher()。

此方法中得到一个LauncherModel对象的引用,LauncherModel这个类中有个回调接口。对LauncherModel进行初始化的时候

public void initialize(Callbacks callbacks){
           synchronized(mLock) {
                 mCallbacks= new WeakReference<Callbacks>(callbacks);
        }
}

由于Launcher实现了Callback接口。在mModel中,将传入的Launcher对象向下转型为Callback赋值给mCallbacks变量。并在LauncherModel中获得了一个Callbacks的软引用。通过这一过程,Launcher对象作为CallbackmModel进行绑定,当mModel后续进行操作时,Launcher可以通过回调得到结果

 

2、  AppWidgetHost.startListening(),

作用:帮助Launcher管理AppWidget,并且能够捕获长按事件,使得应用可以正常的删除、添加AppWidget。通过调用mAppWidgetHost.startListening()方法,开启监听。

 

3、  checkForLocaleChange()

检查本地文件的配置与当前设备的配置是否一致,如果不一致,则更新配置,并且清空IconCache,因为配置的改变可能会改变语言环境,所以需要清空IconCache中的内容重新加载。

 

4、  setupViews(),对所有的UI控件进行加载和配置

DragLayer dragLayer = (DragLayer)findViewById(R.id.drag_layer);

dragLayer.setDragController(dragController);

DragLayer继承自FrameLayout,是整个Launcher的根容器。当快捷图标或者AppWidget被拖拽时,事件的处理就在DragLayer进行操作的。DragController可以帮助实现拖拽。

 

在loadHotseats();中,加载hotseats 增加intent意图启动的activity。

 

dragController.setDragScoller(workspace);

dragController.setDragListener(deleteZone);

dragController.setScrollView(dragLayer);

dragController.setMoveTarget(workspace);

对workspace,deleteZone进行拖拽,move等动作的监听。

dragController.addDropTarget(workspace);

dragController.addDropTarget(deleteZone);

在workspace,deleteZone中注册增加目标如application,appwidget等控件的监听。

 

5、registerContentObservers(),设置内容监听器

6、LauncherModel.startLoader(),为Launcher加载Workspace和AllApps中的内容

if(!mRestoring) {

         //mModel.setmAppsLoading(true);

    mModel.startLoader(thistrue);

}

之后调用

public void startLoader(Context context,boolean isLaunching,boolean onlyLoadAllApp) {

…  …

mLoaderTask =new LoaderTask(context, isLaunching,onlyLoadAllApp);

sWorker.post(mLoaderTask);

}

说明:mModel.startLoader(。。,。。)是开启一个线程,设置线程的优先级NORM_PRIORITY,开始load桌面图标对应的数据库,这个过程是和Launcher.onCreate()同时进行的;

mModel.startLoader(。。,。。) à  LoaderTask.java的run()方法,加载桌面图标对应的数据库的值,这些值能把这些图标显示在workspace屏幕上。

public voidrun() {

… …

    keep_running: {

         ……

        if (loadWorkspaceFirst) {

               if (DEBUG_LOADERS)Log.d(TAG, "step 1: loading workspace");

                loadAndBindWorkspace();

           } else {

                if (DEBUG_LOADERS)Log.d(TAG, "step 1: special: loading all apps");

                loadAndBindAllApps();

            }

            if (mStopped) {

                break keep_running;

            }

                            ……

              waitForIdle();

                // second step

  if(!mOnlyLoadAllApp){// here , we do not load other ,only All_app because of All_APP Switch

       if (loadWorkspaceFirst) {

           if (DEBUG_LOADERS) Log.d(TAG, "step 2:loading all apps");

               loadAndBindAllApps();

            } else {

            if (DEBUG_LOADERS) Log.d(TAG, "step 2:special: loading workspace");

                loadAndBindWorkspace();

              }

       }

  }……

}

 

加载的工作由两部分组成,第一部分是为Workspace加载内容,第二部分则是为AllApps加载内容。每一部分的加载又可以分为两个步骤:

 

1、由LauncherModel完成,主要工作是从数据库中读取信息,并且按类别将内容项分装到不同的数据结构中。

2、由Launcher来完成,通过LauncherModel.Callbacks接口定义的回调方法,从LauncherModel

中获取的数据,将其显示到桌面。

 

第一部分在loadWorkspace中,从ContentProvider获取指定URI中的数据,并将它们分类存放到指定的数据结构中。分类的标准有两条:1、item的类型。包括ITEM_TYPE_APPLICATION  ,ITEM_TYPE_SHORTCUT ,ITEM_TYPE_USER_FOLDER,ITEM_TYPE_APPWIDGET,ITEM_TYPE_LIVE_FOLDER五类。2、item所属的容器。包括CONTAINER_DESKTOP

以及其它(主要指文件夹)。

 

LauncherModel在读取完数据之后,通过LauncherModel.bindWorkspace()将数据传给到Launcher。进入LauncherModel.bindWorkspace()中

 

在bindWorkspace中,

Launcher的内容绑定分为五步:分别对应着startBinding()、bindItems()、bindFolders()、bindAppWidgets()、finishBindingItems()的调用。

 

第二部分AllApps的内容加载loadAndBindAllApps

首先是查询所有的App了,通过向PackagedManager发送指定的Intent就能够获得安装好的应用的信息。查询完毕之后,将数据封装到ArrayList<ApplicationInfo>对象中,然后通过Callbacks.bindAllApplication()或Callbacks.bindAppsAdded()将数据传给Launcher。

 

在这个方法中,还涉及到app排序问题,

Collections.sort(apps,newResolveInfo.DisplayNameComparator(packageManager));

至此All Apps页面的加载完成。

 

其中all app布局显示在从Callbacks.bindAllApplications –> setApps(à addApps()  à

initLayout() à setViewInLayout()(其中通过mHandler.sendEmptyMessage(SORTFINISH);) à

handleMessage() –> 显示屏上app如何布局

 

 

四、workspace触摸事件处理过程

在Launcher的View tree中,从上到下的主要的节点有,DragLayerWorkspace

CellLayout。DragLayer层的主要任务是负责对图标和AppWidget进行拖拽,Workspace则主要负责左右滑动,CellLayout则用于容纳各种桌面的快捷方式

桌面滑动功能主要分两步:1、在onInterceptTouchEvent中进行拦截。2、在onTouchEvent中进行滑动。

在workspace.java中的onInterceptTouchEvent()函数中中

TOUCH_STATE_SCROLLING  状态—> 正在滑动

TOUCH_STATE_REST   状态—> 初始化状态,未滑动

acquireVelocityTrackerAndAddMovement(ev)获取速度跟踪器,记录各个时刻的速度。并且添加当前的MotionEvent以记录更行速度值。  

public booleanonInterceptTouchEvent(MotionEvent ev) {

                   ……

       return mTouchState != TOUCH_STATE_REST;

}

只有进入了滑动状态,才进行拦截,进入onTouchEvent执行滑动操作。当mTouchState != TOUCH_STATE_REST  时,就说明没有进入滑动状态。(因为return  true)。

当mTouchState==TOUCH_STATE_REST时,不需要任何滑动操作,将MotionEvent向子View传递。

开始桌面静止,则mTouchState==TOUCH_STATE_REST,触发switch分支中

MotionEvent.ACTION_DOWN的代码。记录按下点的坐标,设置mAllowLongPress=true。由于mTouchState=TOUCH_STATE_REST,所以动作被传向了子View。接下来,在长按事件被触发之前移动手指则会在代码中调用enableChildrenCache(mCurrentScreen - 1,mCurrentScreen + 1)来决定是否进入滑动状态。进入滑动状态之后mTouchState的值就变为TOUCH_STATE_SCROLLING,然后onTouchEvent中的操作就会被用,开始滑动。

 

在workspace中的onTouchEvent()函数,对接受到的不同的事件进行了分类的处理,大致可以将功能分类为:

1、当接受到ACTION_DOWN时,若滑动正在进行,则停止。

2、当接受到ACTION_MOVE时,根据当前的状态调用scrollBy进行滑动。

3、当接受到ACTION_UP时,根据当前所滑动的位移和速度,判断松手后进入到哪一个分屏。

 

 

在Workspace.Java类实现,相关方法有: 
1) computeScroll():重写了父类的computeScroll();主要功能是计算拖动的位移量、更新背景、设置要显示的屏幕(setScreen(mCurrentScreen);)

。 
2) dispatchDraw():重写了父类的dispatchDraw();主要功能是绘制指定的屏幕,可以绘制当前一屏,也可以绘制当前屏幕和下一屏幕,也可以绘制所有的屏幕,这儿的绘制指显示屏幕上的child(例如:app、folder、Wiget)。 


3) onMeasure():重写了父类的onMeasure();主要功能是设置屏幕的显示大小。由每个child的measure()方法设置。 


4) onLayout():重写了父类的onLayout();主要功能是设置屏幕的显示位置。由child的layout()方法设置。 

 

五、Drop& Drag模型:DragController.java  处理拖曳动作的函数

         DragSource:可以拖动对象来源的容器。

在launcher中主要有AllAppGridView,workspace等。

 将调用此接口:voidonDropCompleted(View target, boolean success,int x,int y);

 

DropTarget:可以放置被拖动的对象的容器。

在launcher中有folder,workspace等,一个View既可以是Dragsource也可以是DropTarget。

 

主要包含以下几个接口:

boolean acceptDrop(DragSource source, intx, int y, int xOffset, int yOffset, Object dragInfo);

acceptDrop函数用来判断dropTarget是否可以接受item放置在自己里面。

 

void onDragEnter(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

          onDragEnter是item被拖动进入到一个dropTarget的时候的回调。

 

void onDragOver(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

          onDragOver是item在上一次位置和这一次位置所处的dropTarget相同的时候的回调。

 

void onDragExit(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

          onDragExit是item被拖出dropTarget时的回调。

 

boolean onDrop(DragSource source, int x,int y, int xOffset, int yOffset, Object dragInfo);

     onDrop是item被放置到dropTarget时的回调。 

 

例如:onDrop在drop()方法中被调用。

Drop()被DragController.java中的onInterceptTouchEvent()或onTouchEvent()调用

    privateboolean drop(float x, float y) {

       final int[] coordinates = mCoordinatesTemp;

       DropTarget dropTarget = findDropTarget((int) x, (int) y,coordinates);

       Log.d(TAG, "dropTarget exist is "+ (dropTarget!=null));

       if (dropTarget != null) {

           dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],

                    (int) mTouchOffsetX,(int) mTouchOffsetY, mDragView, mDragInfo);

//判断dropTarget是否接受接受item放置

           if (dropTarget.acceptDrop(mDragSource, coordinates[0],coordinates[1],

                    (int) mTouchOffsetX,(int) mTouchOffsetY, mDragView, mDragInfo)) {

                dropTarget.onDrop(mDragSource,coordinates[0], coordinates[1],

                        (int) mTouchOffsetX,(int) mTouchOffsetY, mDragView, mDragInfo);

               mDragSource.onDropCompleted((View) dropTarget, true);

                return true;

           } else {

               mDragSource.onDropCompleted((View) dropTarget, false);

                return true;

           }

       }

       return false;

}

 

六、 Launcher 中 View 、ViewGroup事件处理:

        事件处理主要方法:

1)public booleandispatchTouchEvent(MotionEvent ev)  这个方法用来分发TouchEvent

2)public booleanonInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent(只有ViewGroup中有此函数

3)public booleanonTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent(ViewGroup与View中都有)

需要注意以下几点:
1、onInterceptTouchEvent()返回true,那么这个方法只会拦截动作ACTION_DOWN。

2、onInterceptTouchEvent()负责事件分发(事件传递方向),决定了Touch事件是否要向它包含的子View继续传递。

3、onTouchEvent()负责事件处理。决定了事件及后续事件是否继续向上传递。

 

 

当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的dispatchTouchEvent ,然后由  dispatchTouchEvent 方法进行分发,

 

1)如果dispatchTouchEvent返回true ,则交给这个view(本view的onTouchEvent处理,

 

2)如果dispatchTouchEvent返回 false ,则交给这个 view(本view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,

 

3)如果interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,

(本ViewGroup的interceptTouchEvent 只能收到down事件,本ViewGroup的onTouchEvent能收到down,move,up事件,子view不能收到事件)

 

4)如果interceptTouchEvent返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。(本ViewGroup的onInterceptTouchEvent能收到down,move,up事件,本ViewGroup的onTouchEvent没有收到事件;之后(指onInterceptTouchEvent接受所有事件后)子view的onTouchEvent能收到up,move,down事件)

 

5)如果事件传递到某一层的子 view 的onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。

(本view的onTouchEvent只能收到down事件,不能收到move,up事件

 

6)而如果传递到最上面的onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。

 

7)如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

注意1:只要onInterceptTouchEvent()返回false,而且目标控件View::onTouchEvent()返回true,那么事件的每一个动作(按下、移动、抬起等)会都会首先传递到onInterceptTouchEvent()中。

 

注意2:如果事件传递到某一层的子 view  onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会消失,而且接收不到下一次事件。(一次事件指的是 down  up 之间的一系列事件)

 

总结一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent则不一定,总体来看, onInterceptTouchEvent是自rootview向下传递, onTouchEvent正好相反。

 

 

备注:关于onClick、onLongClick及onTouchEvent时序上处理过程分析:

在一个View中同时覆写了onClick、onLongClick及onTouchEvent的话,onTouchEvent是最先捕捉到ACTION_DOWN和ACTION_UP事件的,其次才可能触发onClick或者onLongClick。
1,onTouch返回false
首先是onTouch事件的down事件发生(返回false),此时,如果长按,触发onLongClick事件;然后是onTouch事件的up事件发生,up完毕,最后触发onClick事件。

2,onTouch返回true
首先是onTouch事件的down事件发生,然后是onTouch事件的up事件发生;期间不触发onClick和onLongClick事件

3,onTouch:down返回true,up返回false:结果同二。


详细分析:

onTouch事件中:down事件返回值标记此次事件是否为点击事件(返回false,是点击事件;返回true,不记为点击事件(为该事件已经被处理)),而up事件标记此次事件结束时间,也就是判断是否为长按。只要当down返回true时候,系统将不把本次事件记录为点击事件,也就不会触发onClick或者onLongClick事件了。因此尽管当up的时候返回false,系统也不会继续触发onClick事件了。

4,onTouch:down返回false,up返回true:
首先是onTouch事件的down事件发生,此时:
长按,触发onLongClick事件,然后是onTouch事件的up事件发生,完毕。
短按,先触发onTouch的up事件,到一定时间后,自动触发onLongClick事件。
机制分析:
  onTouch事件中:down事件返回值标记此次事件是否为点击事件(返回false,是点击事件;返回true,不记为点击事件),而up事件标记此次事件结束时间,也就是判断是否为长按。
  当down返回false,标记此次事件为点击事件,而up返回了true,则表示此次事件一直没有结束,也就是一直长按下去了,达到长按临界时间后,自然触发长按事件,而onClick事件没有触发到。

 

总结:

onLongClick发生只有在down为false,up为任意时发生;

Onclick发生在down为false,up为false时发生,

七、关于launcher中

Activity 、View 、Window 、 ViewRoot 、DecorRoot介绍及几者之间的关系:

相关类图


(1)  activity: 是逻辑上的东西,增加了生命周期管理等. 里面具体的东西也是view。而且启动activity的实现也是往window里加view,包含一个Window,该Window在Activity的attach方法中通过调用PolicyManager.makeNewWindow创建。

 

(2)  View:  最基本的UI组件,表示屏幕上的一个矩形区域,通过 setContentView这个接口进Window显示。1、所有高级UI组件都继承View类而实现的2、一个View在屏幕上占据一块矩形区域3、负责渲染4、负责处理发生的事件5、设置是否可见6、设置是否可以获得焦点等

 

(3). ViewGroup  1、ViewGroup View的子类2、View的容器 3、负责对添加进ViewGroup的View进行布局 4、一个ViewGroup可以加入到另一个ViewGroup5、各种layout继承自ViewGroup。ViewGroup  与View关系图如下

 

(4). widget 1、界面中展示的各个小组件2、有独立的事件处理能力3、所有Wiget组件都是继承View而来,继承自View或ViewGroup。

(5)  Window:该类提供了一组通用的窗口(Window)操作API,这里的窗口仅仅是程序层面上的,WmS所管理的窗口并不是Window类,而是一个View或者ViewGroup类,一般就是指DecorView类,即一个DecorView就是WmS所管理的一个窗口。Window是一个abstract类型。

 

(6)  PhoneWindow:是Android中的最基本的窗口系统,每个Activity均会创建一个PhoneWindow对象,是Activity和整个View系统交互的接口。

 

(7)  DecorView:DecorView是当前Activity所有View的祖先,该类是一个FrameLayout的子类,并且是PhoneWindow中的一个内部类。DecorView就是对普通的FrameLayout进行了一定的修饰,比如添加一个通用的Titlebar,并响应特定的按键消息等。

Decor View结构图:

1、DecorView为整个Window界面的最顶层View。

2、DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。

3、LinearLayout里有两个FrameLayout子元素。

 (20)为标题栏显示界面。只有一个TextView显示应用的名称。也可以自定义标题栏,载入后的自定义标题栏View将加入FrameLayout中。

 (21)为内容栏显示界面。就是setContentView()方法载入的布局界面,加入其中。

4、派发从ViewRoot分发来的key、touch、trackball等外部事件;

5、作为PhoneWindow与ViewRoot之间的桥梁,ViewRoot通过DecorView设置窗口属性。


(9) ViewRoot:

1. ViewRoot负责协调decorview与windowmanager直接绘图、事件处理;

2. 向DecorView分发收到的用户发起的event事件,如按键,触屏,轨迹球等事件;

3. 与WindowManagerService交互,完成整个Activity的GUI的绘制。

注意: ViewRoot只是DecorView的代理来接收WindowManagerService发过来的消息,DecorView才是activity Window的展示内容的平台。(ViewRoot实际是一个HandlerViewRoot建立主ViewWindowsManger通讯的桥梁)。

八、View中常用方法简介
onFinishInflate()

当View和它的所有子对象从XML中导入之后,调用此方法 
onMeasure(int, int)

View会调用此方法,来确认自己及所有子对象的大小 
onLayout(boolean, int, int, int, int,int, int)

当View要为所有子对象分配大小和位置时,调用此方法 
onSizeChanged(int, int, int, int)

 当View大小改变时,调用此方法 

onDraw(Canvas)

当View要绘制它的内容时,调用此方法 (ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法)

dispatchDraw()

绘制子视图调用(在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法)

onKeyDown(int,KeyEvent)

当一个新的按键事件发生时,调用此方法 
onKeyUp(int, KeyEvent)

当一个按键释放事件发生时,调用此方法 
onMotionEvent(MotionEvent)

当一个动作事件(如触摸)发生时,调用此方法 
onFocusChanged(boolean, int)

当View获得或失去焦点时,调用此方法 

onAttachedToWindow()

当View附加到一个窗体上时,调用此方法 

onDetachedFromWindow()

当View离开它的窗体时,调用此方法 

onWindowVisibilityChanged(int)

当窗口中包含的可见的view发生变化时触发

computeScroll()

主要功能是计算拖动的位移量、更新背景、设置要显示的屏幕。

 

 

九、常用知识点

1、  Ctrl+shift+R 可以查找该工程中的文件(知道文件名但不知道路径时可以使用)。

2、  Ctrl+O 显示该类中的所有方法。

3、  Alt+ß    返回

3、./mk sp6820gb u adrpac system  当修改某一个system目录下的文件,可以使用此命令打包成一个system.img文件。

4、在ubuntu下面一工程下查找某一个字符串可以使用

Find –name ‘xxx.xxx’ | xargs grep  ‘xxx’ |  grep –v “\.svn/*”

查找xxx.xxx文件中的xxx字符串,不显示带.svn的文件

4、  关于抓log方法 –> 在cmd中使用adb  logcat –v  time 就会显示log


这篇关于Launcher介绍总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/863927

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

二分最大匹配总结

HDU 2444  黑白染色 ,二分图判定 const int maxn = 208 ;vector<int> g[maxn] ;int n ;bool vis[maxn] ;int match[maxn] ;;int color[maxn] ;int setcolor(int u , int c){color[u] = c ;for(vector<int>::iter

整数Hash散列总结

方法:    step1  :线性探测  step2 散列   当 h(k)位置已经存储有元素的时候,依次探查(h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中,S为 数组长度。 HDU 1496   a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 。 x在 [-100,100] 解的个数  const int MaxN = 3000

状态dp总结

zoj 3631  N 个数中选若干数和(只能选一次)<=M 的最大值 const int Max_N = 38 ;int a[1<<16] , b[1<<16] , x[Max_N] , e[Max_N] ;void GetNum(int g[] , int n , int s[] , int &m){ int i , j , t ;m = 0 ;for(i = 0 ;