展会信息港展会大全

探秘 widget 之 launcher 添加 widget 的流程分析
来源:互联网   发布日期:2015-10-03 10:38:47   浏览:1636次  

导读:最近打算研究下android的widget相关问题,并把一些心得在此稍作记录,哈哈,等研究完成了,如果有必要的话,也会把改动的源码贴出来,以飨读者。今天先来看看launcher2中添加widget的流程。添加widget首先需要在......

最近打算研究下android的widget相关问题,并把一些心得在此稍作记录,哈哈,等研究完成了,如果有必要的话,也会把改动的源码贴出来,以飨读者。今天先来看看launcher2中添加widget的流程。

添加widget首先需要在laucher的空白处长按,所以首先定位在laucher的 public boolean onLongClick(View v) 中,看到:

if (mWorkspace.allowLongPress()) {

if (cellInfo.cell == null) {

if (cellInfo.valid) {

// User long pressed on empty space

mWorkspace.setAllowLongPress(false);

mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,

HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);

showAddDialog(cellInfo);

}

} else {

if (!(cellInfo.cell instanceof Folder)) {

// User long pressed on an item

mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,

HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);

mWorkspace.startDrag(cellInfo);

}

}

}

可以看到跳转到了showAddDialog(cellInfo),寻找到:

private void showAddDialog(CellLayout.CellInfo cellInfo) {

mAddItemCellInfo = cellInfo;

mWaitingForResult = true;

showDialog(DIALOG_CREATE_SHORTCUT);

}

可以看到他携带着DIALOG_CREATE_SHORTCUT参数创建了一个Dialog,携带参数跳入Launcher.java的父类Activity.java的showDialog()方法,最终到达Launcher.java的onCreateDialog(int id)方法,代码如下:

@Override

protected Dialog onCreateDialog(int id) {

switch (id) {

case DIALOG_CREATE_SHORTCUT:

return new CreateShortcut().createDialog();

case DIALOG_RENAME_FOLDER:

return new RenameFolder().createDialog();

}

return super.onCreateDialog(id);

}

跳转到了CreateShortcut()的createDialog()方法:

Dialog createDialog() {

mWaitingForResult = true;

mAdapter = new AddAdapter(Launcher.this);

final AlertDialog.Builder builder = new AlertDialog.Builder(Launcher.this);

builder.setTitle(getString(R.string.menu_item_add_item));

builder.setAdapter(mAdapter, this);

builder.setInverseBackgroundForced(true);

AlertDialog dialog = builder.create();

dialog.setOnCancelListener(this);

dialog.setOnDismissListener(this);

dialog.setOnShowListener(this);

return dialog;

}

这里可以看到一个 AddAdapter类,跳转去看看,这个就是定义长按后出现的对话框的内容:

public static final int ITEM_SHORTCUT = 0;

public static final int ITEM_APPWIDGET = 1;

public static final int ITEM_LIVE_FOLDER = 2;

public static final int ITEM_WALLPAPER = 3;

如果我们需要在原来的对话框中添加新的内容,那么首先需要修改的就是这里,我们回到之前的地方接着往下走,dialog响应的点击事件,public void onClick(DialogInterface dialog, int which) :

case AddAdapter.ITEM_APPWIDGET: {

int appWidgetId = Launcher.this.mAppWidgetHost.allocateAppWidgetId();

//这里生成了一个appWidgetId,供后面绑定AppWidgetProvider使用

Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);

//新建一个intent,该intent是打开一个现实Widgets列表的activity,该activity对应类AppWidgetPickActivity

pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

// start the pick activity

//设置EXTRA_APPWIDGET_ID

startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);

break;

}

这里看到点击widget条目之后,跳转打开一个新的pickIntent,其实际运行的为packages/apps/Settings/src/com/android/settings/AppWidgetPickActivity.java:

先在onCreate方法中创建了一个InstalledAppWidgets列表,该列表就是我们在界面上能见到的所有widgets。

在点击一个widgets,进入AppWidgetPickActivity.onClick事件监听,注意阅读该方法代码,它会进入else:

if (intent.getExtras() != null) {

// If there are any extras, it's because this entry is custom.

// Don't try to bind it, just pass it back to the app.

setResultData(RESULT_OK, intent);

} else {

try {

mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent());

//绑定选中的桌面组件与mAppWidgetId

result = RESULT_OK;//设置返回结果为ok

activity执行结束后面都会进入launcher.onActivityResult,查看该函数方法有两个关键的case:

case REQUEST_PICK_APPWIDGET:

addAppWidget(data);

break;

case REQUEST_CREATE_APPWIDGET:

completeAddAppWidget(data, mAddItemCellInfo);

接着跳转到launcher的addAppWidget(Intent data)里data为传递来的appWidgetId:

void addAppWidget(Intent data) {

// TODO: catch bad widget exception when sent

int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId);

//先判断是否有配置页

if (appWidget.configure != null) {

// Launch over to configure widget, if needed

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);

intent.setComponent(appWidget.configure);

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);

} else {

// Otherwise just add it

onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);

}

}

通过onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);跳转回launcher.onActivityResult的

case REQUEST_CREATE_APPWIDGET:

completeAddAppWidget(data, mAddItemCellInfo);

@param data The intent describing the appWidgetId.

* @param cellInfo The position on screen where to create the widget.

*/

private void completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo)

在 completeAddAppWidget(data, mAddItemCellInfo)中完成widget的添加。

private void completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo) {

Bundle extras = data.getExtras();

int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

if (LOGD) Log.d(TAG, "dumping extras content=" + extras.toString());

//由appWidgetId获取widget的信息,例如大小等

AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);

// Calculate the grid spans needed to fit this widget

CellLayout layout = (CellLayout) mWorkspace.getChildAt(cellInfo.screen);

int[] spans = layout.rectToCell(appWidgetInfo.minWidth, appWidgetInfo.minHeight);

// Try finding open space on Launcher screen

final int[] xy = mCellCoordinates;

if (!findSlot(cellInfo, xy, spans[0], spans[1])) {

if (appWidgetId != -1) mAppWidgetHost.deleteAppWidgetId(appWidgetId);

return;

}

// Build Launcher-specific widget info and save to database

LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId);

launcherInfo.spanX = spans[0];

launcherInfo.spanY = spans[1];

LauncherModel.addItemToDatabase(this, launcherInfo,

LauncherSettings.Favorites.CONTAINER_DESKTOP,

mWorkspace.getCurrentScreen(), xy[0], xy[1], false);

if (!mRestoring) {

mDesktopItems.add(launcherInfo);

// Perform actual inflation because we're live

launcherInfo.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);

launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo);

launcherInfo.hostView.setTag(launcherInfo);

mWorkspace.addInCurrentScreen(launcherInfo.hostView, xy[0], xy[1],

launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());

}

赞助本站

人工智能实验室

相关热词: widget launcher

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港