android AppWidget 桌面快捷添加小部件流程

Luuncher onCreate stupViews 初始化com.android.launcher3
.Workspace 控件,构造方法中实现setOnTouchListener(new WorkspaceTouchListener(mLauncher, this));
在 WorkspaceTouchListener的onLongPress中

弹出OptionsPopupView.showDefaultOptions(mLauncher, mTouchDownPoint.x, mTouchDownPoint.y);,长按桌面弹出小部件选择,选择小部件

/** Returns WidgetsFullSheet that was opened, or null if nothing was opened. /
@Nullable
public static WidgetsFullSheet openWidgets(Launcher launcher) {
if (launcher.getPackageManager().isSafeMode()) {
// 在安全模式下無法使用小工具
Toast.makeText(launcher, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
return null;
} else {
return WidgetsFullSheet.show(launcher, true /
animated */);
}
}

WidgetsFullSheet 控件中加载小部件到 WidgetsRecyclerView中

/** Gets the {@link WidgetsRecyclerView} which shows all widgets in {@link WidgetsFullSheet}. */
@VisibleForTesting
public static WidgetsRecyclerView getWidgetsView(Launcher launcher) {
return launcher.findViewById(R.id.primary_widgets_list_view);
}
在BaseWidgetSheet的onLongClick中开发创建Widget, beginDraggingWidget方法具体创建,走到startDrag方法

private boolean beginDraggingWidget(WidgetCell v) {
// Get the widget preview as the drag representation
WidgetImageView image = v.getWidgetView();

// If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
// we abort the drag.
if (image.getDrawable() == null && v.getAppWidgetHostViewPreview() == null) {
    return false;
}

PendingItemDragHelper dragHelper = new PendingItemDragHelper(v);
dragHelper.setRemoteViewsPreview(v.getRemoteViewsPreview());
dragHelper.setAppWidgetHostViewPreview(v.getAppWidgetHostViewPreview());

if (image.getDrawable() != null) {
    int[] loc = new int[2];
    getPopupContainer().getLocationInDragLayer(image, loc);

    dragHelper.startDrag(image.getBitmapBounds(), image.getDrawable().getIntrinsicWidth(),
            image.getWidth(), new Point(loc[0], loc[1]), this, new DragOptions());
} else {
    View preview = v.getAppWidgetHostViewPreview();
    int[] loc = new int[2];
    getPopupContainer().getLocationInDragLayer(preview, loc);

    Rect r = new Rect(0, 0, preview.getWidth(), preview.getHeight());
    dragHelper.startDrag(r, preview.getMeasuredWidth(), preview.getMeasuredWidth(),
            new Point(loc[0], loc[1]), this, new DragOptions());
}
close(true);
return true;

}

首先调用AppWidgetHostView.setAppWidget(int appWidgetId, AppWidgetProviderInfo info)
,设置AppWidget的显示View和padding,appWidgetId默认-1

拖动Widget ,DragController.DragListener的实现WidgetHostViewLoader.onDragStart
(),

 /** * Start preloading the widget. */
    private boolean preloadWidget() { 
        final LauncherAppWidgetProviderInfo pInfo = mInfo.info;

        if (pInfo.isCustomWidget()) { 
            return false;
        }
        final Bundle options = mInfo.getDefaultSizeOptions(mLauncher);

        // If there is a configuration activity, do not follow thru bound and inflate.
        if (mInfo.getHandler().needsConfigure()) { 
            mInfo.bindOptions = options;
            return false;
        }

        mBindWidgetRunnable = new Runnable() { 
            @Override
            public void run() { 
                mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
                if (LOGD) { 
                    Log.d(TAG, "Binding widget, id: " + mWidgetLoadingId);
                }
                if (new WidgetManagerHelper(mLauncher).bindAppWidgetIdIfAllowed(
                        mWidgetLoadingId, pInfo, options)) { 

                    // Widget id bound. Inflate the widget.
                    mHandler.post(mInflateWidgetRunnable);
                }
            }
        };

        mInflateWidgetRunnable = new Runnable() { 
            @Override
            public void run() { 
                if (LOGD) { 
                    Log.d(TAG, "Inflating widget, id: " + mWidgetLoadingId);
                }
                if (mWidgetLoadingId == -1) { 
                    return;
                }
                AppWidgetHostView hostView = mLauncher.getAppWidgetHost().createView(
                        (Context) mLauncher, mWidgetLoadingId, pInfo);
                mInfo.boundWidget = hostView;

                // We used up the widget Id in binding the above view.
                mWidgetLoadingId = -1;

                hostView.setVisibility(View.INVISIBLE);
                int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(mInfo);
                // We want the first widget layout to be the correct size. This will be important
                // for width size reporting to the AppWidgetManager.
                DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0],
                        unScaledSize[1]);
                lp.x = lp.y = 0;
                lp.customPosition = true;
                hostView.setLayoutParams(lp);
                if (LOGD) { 
                    Log.d(TAG, "Adding host view to drag layer");
                }
                mLauncher.getDragLayer().addView(hostView);
                mView.setTag(mInfo);
            }
        };

        if (LOGD) { 
            Log.d(TAG, "About to bind/inflate widget");
        }
        mHandler.post(mBindWidgetRunnable);
        return true;
    }

第一步,getAppWidgetHost().allocateAppWidgetId获取服务器分配的 appWidgetId

第二部,AppWidgetManager#bindAppWidgetIdIfAllowed(int, UserHandle, ComponentName, Bundle)
为给Widget设置appWidgetId。如果成功,应用程序的AppWidgetProvider将收到ACTION_APPWIDGET_UPDATE更新广播。
绑定AppWidgetID成功后,初始化Widget界面,最终调用mLauncher.getDragLayer().addView(hostView);
添加布局到Draglayer 底层布局中。

    原文作者:空间维度
    原文地址: https://blog.csdn.net/u012743062/article/details/122365762
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞