Launcher8.0启动流程的第四步,第2小步。定义OverViewPanel,关于OverViewPanel的布局整体在res里面以xml文件形式存在,而对于其细节层面,比如点击之后有什么用则再java层详细定义,而第2小步则是定义OverViewPanel三个按钮的功能。
在setupView的完整源码,以setupOverviewPanel方法为分界线,分为3小步。说明setupOverviewPanel非常复杂。和setupview方法一样,setupOverviewPanel也是在Launcher类里面。所创建内容服务于Launcher整体。
那么什么是OverviewPanel?
在Launcher使用时,长按桌面空白处,我们会发现,workspace缩小,hotseat消失,并且在下方出现三个选项:wallpapers,widget,home settings 这个提供特殊选项的栏,就叫做OverviewPanel
其源码如下:
private void setupOverviewPanel() {
mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel);
View wallpaperButton = findViewById(R.id.wallpaper_button);
new OverviewButtonClickListener(ControlType.WALLPAPER_BUTTON) {
@Override
public void handleViewClick(View view) {
onClickWallpaperPicker(view);
}
}.attachTo(wallpaperButton);
wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
mWidgetsButton = findViewById(R.id.widget_button);
new OverviewButtonClickListener(ControlType.WIDGETS_BUTTON) {
@Override
public void handleViewClick(View view) {
onClickAddWidgetButton(view);
}
}.attachTo(mWidgetsButton);
mWidgetsButton.setOnTouchListener(getHapticFeedbackTouchListener());
View settingsButton = findViewById(R.id.settings_button);
boolean hasSettings = hasSettings();
if (hasSettings) {
new OverviewButtonClickListener(ControlType.SETTINGS_BUTTON) {
@Override
public void handleViewClick(View view) {
onClickSettingsButton(view);
}
}.attachTo(settingsButton);
settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
} else {
settingsButton.setVisibility(View.GONE);
}
mOverviewPanel.setAlpha(0f);
}
源码逻辑清晰,首先获取overview_panel的View,然后依次创建wallpaper,widget,settings这3个buttom。
overview_panel是oncreate流程第三步统一创建对象的时候,在UI布局文件Launcher.xml里面提到的多个组成Launcher的其中之一。核心就是三个button。
首先认真研读第一个wallpaperButton 的创建,而后举一反三。
View wallpaperButton = findViewById(R.id.wallpaper_button);
new OverviewButtonClickListener(ControlType.WALLPAPER_BUTTON) {
@Override
public void handleViewClick(View view) {
onClickWallpaperPicker(view);
}
}.attachTo(wallpaperButton);
wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
这里简化代码一共有三步:
创建View对象wallpaperButton
创建listener并绑定到View上。
new OverviewButtonClickListener().attachTo(wallpaperButton);
View.setOnTouchListener
首先关注view的获取。
Launcher.xml里面有一栏说明Launcher的overview_panel布局是调用了overview_panel.xml
<include layout="@layout/overview_panel"
android:id="@+id/overview_panel"
android:visibility="gone" />
然后看overview_panel.xml 充分简化都的代码,一个线性布局,里面有三个textView,对应三个button
<LinearLayout >
<TextView android:id="@+id/wallpaper_button"/>
<TextView android:id="@+id/widget_button"/>
<TextView android:id="@+id/settings_button" />
</LinearLayout>
接着创建clicklistener并attach。
public void attachTo(View v) {
v.setOnClickListener(this);
v.setOnLongClickListener(this);
}
其意思是将传入的View给定方法的listener。
所以new OverviewButtonClickListener().attachTo(wallpaperButton);
的含义是将创建的类的onclick方法绑定到wallpaperButton。
下面是OverviewButtonClickListener类的onclick和onLongClick方法的源码。
@Override
public void onClick(View view) {
if (shouldPerformClick(view)) {
handleViewClick(view, Action.Touch.TAP);
}
}
@Override
public boolean onLongClick(View view) {
if (shouldPerformClick(view)) {
handleViewClick(view, Action.Touch.LONGPRESS);
}
return true;
}
在OverviewButtonClickListener这个自定义的buttonlistener里面,点击和长按都是触发handleViewClick方法。
而我们创建的OverviewButtonClickListener则是重写了handleViewClick方法。
public void handleViewClick(View view) {
onClickWallpaperPicker(view);
}
于是,这里创建对象并attach,就是当我们点击这个按钮时,要触发重写的方法。在wallpaperButton里面,我们写的是onClickWallpaperPicker(view)。
看到这里,我们再回去看三个button的定义,都是在三段式,主要在OverviewButtonClickListener的重写方法上有区别。
然后就是wallpaperButton.setOnTouchListener();就是绑定点击响应。
接下来,认真看三个click方法的代码码
首先是onClickWallpaperPicker进行大幅度删减的代码
public void onClickWallpaperPicker(View v) {
Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER)
.putExtra(Utilities.EXTRA_WALLPAPER_OFFSET, offset);
startActivityForResult(intent);
}
从给出的代码可以看出,这个按钮的功能是通过”Intent.ACTION_SET_WALLPAPER”来启动对应的应用。
手机中,提供设置壁纸功能的应用,比如图库,会打开此intent。 而Launcher在onclick被点击时就会启动对应的应用。
完整代码中有一部分关于intent的详细设定,以及一些保护措施。 但都是为了打开一个可以设壁纸的应用所服务。
接着是onClickAddWidgetButton方法,也是精简版。
public void onClickAddWidgetButton(View view) {
showWidgetsView(true /* animated */, true /* resetPageToZero */);
}
void showWidgetsView(boolean animated, boolean resetPageToZero) {
showAppsOrWidgets(State.WIDGETS, animated, false);
}
private boolean showAppsOrWidgets(State toState, boolean animated, boolean focusSearchBar) {
if (toState == State.APPS) {
mStateTransitionAnimation.startAnimationToAllApps(animated, focusSearchBar);
} else {
mStateTransitionAnimation.startAnimationToWidgets(animated);
}
return true;
}
从代码可以看到,是一个递进调用,过程中对state进行设置,最终调用了mStateTransitionAnimation这个对象的方法。
mStateTransitionAnimation是在Launcher流程第三步创建的第三个对象,负责不同模式间的切换,在onClickAddWidgetButton中完成的是从overview模式到widget模式的切换。
最后是onClickSettingsButton方法
public void onClickSettingsButton(View v) {
Intent intent = new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
.setPackage(getPackageName());
intent.setSourceBounds(getViewBounds(v));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent, getActivityLaunchOptions(v));
}
从代码看出,使用Intent.ACTION_APPLICATION_PREFERENCES来启动Launcher的Settings activity。
这样overviewpanel的三个选项就都完成了。其中wallpapers和settings是启动新的activity , widget是Launcher之间的模式变化。
以上就是第二小步。
第四步的setupView的第三小步:对workspace进行基本绑定。
mWorkspace.setOnLongClickListener(this);
mWorkspace.setup(mDragController);
mWorkspace.lockWallpaperToDefaultPage();
mWorkspace.bindAndInitFirstWorkspaceScreen( );
mDragController.addDragListener(mWorkspace);
首先在workspace上绑定onlongclick方法。里面绑定的是Launcher里面的onlongclick。于是当长按workspace的时候,就会启用Launcher的onlongclick方法。
下面是Launcher中onlongclick关于workspace部分。
@Override
public boolean onLongClick(View v) {
if (v instanceof Workspace) {
if (!mWorkspace.isInOverviewMode()) {
getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
Action.Direction.NONE, ContainerType.WORKSPACE,
mWorkspace.getCurrentPage());
showOverviewMode(true);
}
}
}
Launcher的onlongclick不仅仅绑定在workspace。还有其他模块也绑定。所以触发时需要进行判断。这里在workspace长按,如果长按的时候,不少overview这个模式,则进入overview这个模式。
mWorkspace.setup(mDragController); 在workspace中传入dragcontroller。 Dragcontroller的用途广泛,和拖拽有关的,比如,拖拽时顶部出现的选项栏等等都由Dragcontroller控制。
mWorkspace.lockWallpaperToDefaultPage(); 是设workspace时背景壁纸的偏移量的,Launcher有个壁纸随页面滑动的功能,也就是长壁纸功能。在此功能下,开机时的那一张被设为默认的壁纸起始页面。
mWorkspace.bindAndInitFirstWorkspaceScreen(null ); 绑定起始桌面的默认google search的。正如之前提到,google在开发Launcher的时候特地留了一个google search widget的入口。
mDragController.addDragListener(mWorkspace); 给workspace监听drag的权限
第四步的setupView的第四小步:对allapp和DropTargetBar 及其他设定。
mDropTargetBar = (DropTargetBar) mDragLayer.findViewById(R.id.drop_target_bar);
mAppsView = (AllAppsContainerView) findViewById(R.id.apps_view);
if (mLauncherCallbacks != null && mLauncherCallbacks.getAllAppsSearchBarController() != null) {
mAppsView.setSearchBarController(mLauncherCallbacks.getAllAppsSearchBarController());
} else {
mAppsView.setSearchBarController(new DefaultAppSearchController());
}
mDragController.setMoveTarget(mWorkspace);
mDragController.addDropTarget(mWorkspace);
mDropTargetBar.setup(mDragController);
设置allapp的搜索栏以及提供在workspace顶部能够显示选项按钮。
mDropTargetBar顶部选项按钮,是Launcher.xml的组件之一。
当拖动应用的时候,顶部会给出该应用能够供给的一些选项。
通常有info、remove、disable、uninstall
info:从allapp拖动应用到桌面会出现,将应用拖到info并松开会显示应用的参数
Remove:删掉桌面的快捷方式,allapp中仍然保留
Disable:禁用应用,针对系统应用,这些应用不能被删除,如有需要,可以选择禁用该应用的功能。比如平板的通话和短信功能。
Uninstall:对于用户安装的应用,在拖拽时顶部会有uninstall选项。这是用户在桌面删除手机中应用的唯一方法。 删除应用可以在设置或者其他应用管理软件里面进行。