public static List getWidgetProviders(Context context, boolean refresh) { ArrayList results = new ArrayList (); try { synchronized (sBgLock) { if (sBgWidgetProviders == null || refresh) { HashMap tmpWidgetProviders = new HashMap<>(); AppWidgetManagerCompat wm = AppWidgetManagerCompat.getInstance(context); LauncherAppWidgetProviderInfo info; List widgets = wm.getAllProviders(); for (AppWidgetProviderInfo pInfo : widgets) { info = LauncherAppWidgetProviderInfo.fromProviderInfo(context, pInfo); UserHandleCompat user = wm.getUser(info); tmpWidgetProviders.put(new ComponentKey(info.provider, user), info); } Collection customWidgets = Launcher.getCustomAppWidgets().values(); for (CustomAppWidget widget : customWidgets) { info = new LauncherAppWidgetProviderInfo(context, widget); UserHandleCompat user = wm.getUser(info); tmpWidgetProviders.put(new ComponentKey(info.provider, user), info); } // Replace the global list at the very end, so that if there is an exception, // previously loaded provider list is used. sBgWidgetProviders = tmpWidgetProviders; } results.addAll(sBgWidgetProviders.values()); return results; } } catch (Exception e) { ... } }复制代码
@Override public List getAllProviders() { ArrayList providers = new ArrayList (); for (UserHandle user : mUserManager.getUserProfiles()) { providers.addAll(mAppWidgetManager.getInstalledProvidersForProfile(user)); } return providers; }复制代码
public LauncherAppWidgetProviderInfo(Parcel in) { super(in); initSpans(); }复制代码
这个构造函数调用了initSpans方法,我们接着追寻:
private void initSpans() { LauncherAppState app = LauncherAppState.getInstance(); InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); // We only care out the cell size, which is independent of the the layout direction. Rect paddingLand = idp.landscapeProfile.getWorkspacePadding(false /* isLayoutRtl */); Rect paddingPort = idp.portraitProfile.getWorkspacePadding(false /* isLayoutRtl */); // Always assume we're working with the smallest span to make sure we // reserve enough space in both orientations. float smallestCellWidth = DeviceProfile.calculateCellWidth(Math.min( idp.landscapeProfile.widthPx - paddingLand.left - paddingLand.right, idp.portraitProfile.widthPx - paddingPort.left - paddingPort.right), idp.numColumns); float smallestCellHeight = DeviceProfile.calculateCellWidth(Math.min( idp.landscapeProfile.heightPx - paddingLand.top - paddingLand.bottom, idp.portraitProfile.heightPx - paddingPort.top - paddingPort.bottom), idp.numRows); // We want to account for the extra amount of padding that we are adding to the widget // to ensure that it gets the full amount of space that it has requested. Rect widgetPadding = AppWidgetHostView.getDefaultPaddingForWidget( app.getContext(), provider, null); spanX = Math.max(1, (int) Math.ceil( (minWidth + widgetPadding.left + widgetPadding.right) / smallestCellWidth)); spanY = Math.max(1, (int) Math.ceil( (minHeight + widgetPadding.top + widgetPadding.bottom) / smallestCellHeight)); minSpanX = Math.max(1, (int) Math.ceil( (minResizeWidth + widgetPadding.left + widgetPadding.right) / smallestCellWidth)); minSpanY = Math.max(1, (int) Math.ceil( (minResizeHeight + widgetPadding.top + widgetPadding.bottom) / smallestCellHeight)); }复制代码
public PreviewLoadRequest getPreview(final Object o, int previewWidth, int previewHeight, WidgetCell caller) { String size = previewWidth + "x" + previewHeight; WidgetCacheKey key = getObjectKey(o, size); PreviewLoadTask task = new PreviewLoadTask(key, o, previewWidth, previewHeight, caller); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); return new PreviewLoadRequest(task); }复制代码
@Override public boolean onLongClick(View v) { ... boolean status = beginDragging(v); if (status && v.getTag() instanceof PendingAddWidgetInfo) { WidgetHostViewLoader hostLoader = new WidgetHostViewLoader(mLauncher, v); boolean preloadStatus = hostLoader.preloadWidget(); ... mLauncher.getDragController().addDragListener(hostLoader); } return status; }复制代码
首先调用beginDragging方法:
private boolean beginDragging(View v) { if (v instanceof WidgetCell) { if (!beginDraggingWidget((WidgetCell) v)) { return false; } } else { Log.e(TAG, "Unexpected dragging view: " + v); } // We don't enter spring-loaded mode if the drag has been cancelled if (mLauncher.getDragController().isDragging()) { // Go into spring loaded mode (must happen before we startDrag()) mLauncher.enterSpringLoadedDragMode(); } return true; }复制代码
public void onDragStartedWithItem(PendingAddItemInfo info, Bitmap b, boolean clipAlpha) { int[] size = estimateItemSize(info, false); // The outline is used to visualize where the item will land if dropped mDragOutline = createDragOutline(b, DRAG_BITMAP_PADDING, size[0], size[1], clipAlpha); }复制代码
public void addPendingItem(PendingAddItemInfo info, long container, long screenId, int[] cell, int spanX, int spanY) { switch (info.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: int span[] = new int[2]; span[0] = spanX; span[1] = spanY; addAppWidgetFromDrop((PendingAddWidgetInfo) info, container, screenId, cell, span); break; ... } }复制代码