欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

App Widgets 详解三 Activity中添加App Widgets

程序员文章站 2022-05-30 13:41:35
...

导读

  • 从官方文档可知,App widgets 是微型应用视图,能够嵌入到其他的应用程序(如系统桌面/其他应用的Activity)

  • 由于现在App Widget在实际开发中已经不常见了,本篇简单介绍如何将widget添加到当前Activity

有兴趣深入研究的同学可以看下Launch实现widget的原理

关键API AppWidgetHost 官方文档

  • App Widget 小部件系列其他文章链接:

App Widgets 详解一 简单使用

App Widgets 详解二 Configuration Activity

App Widgets 详解三 Activity中添加App Widgets

App Widgets 详解四 RemoteViews、RemoteViewsService和RemoteViewsFactory

实现步骤

  1. 设置要长按监听的布局
  2. 使用AppWidgetHost.startListening() 监听widget的状态变化
  3. 请求添加一个新的widget:用于选取系统中的widget
  4. 接收添加appwidget和appwidget的配置activity的返回值.分类处理添加widget的逻辑业务

public class ExampleActivity extends AppCompatActivity {
    private AppWidgetHost    mAppWidgetHost;
    private AppWidgetManager mAppWidgetManager;
    private FrameLayout      frameLayout;
    private static final int    REQUEST_PICK_APPWIDGET   = 1;
    private static final int    REQUEST_CREATE_APPWIDGET = 2;
    private static final int    APPWIDGET_HOST_ID        = 0x100;     //用于标识
    private static final String EXTRA_CUSTOM_WIDGET      = "custom_widget";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //1.设置要长按监听的布局
        //这里不一定学我直接监听根布局,写一个ViewGroup重写那三个方法(扩展性更高)
        frameLayout = new FrameLayout(this);

        setContentView(frameLayout);

        frameLayout.setOnLongClickListener(new View.OnLongClickListener() {

            @Override
            public boolean onLongClick(View v) {
                showWidgetChooser();
                return true;
            }
        });


        mAppWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
        mAppWidgetHost = new AppWidgetHost(getApplicationContext(), APPWIDGET_HOST_ID);

        //2.使用AppWidgetHost.startListening() 监听widget的状态变化
        mAppWidgetHost.startListening();


    }

    /**
     * 4.接收添加appwidget和appwidget的配置activity的返回值.分类处理添加widget的逻辑业务
     * <p>
     * 选中了某个widget之后,根据是否有配置来决定直接添加还是弹出配置activity
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case REQUEST_PICK_APPWIDGET:
                    addAppWidget(data);
                    break;
                case REQUEST_CREATE_APPWIDGET:
                    completeAddAppWidget(data);
                    break;
            }
        } else if (requestCode == REQUEST_PICK_APPWIDGET &&
                resultCode == RESULT_CANCELED && data != null) {
            //如果configure Actvity finish掉,已经添加过Widget,就不添加widget
            int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
            if (appWidgetId != -1) {
                mAppWidgetHost.deleteAppWidgetId(appWidgetId);
            }
        }
    }

    /**
     * 选中了某个widget之后,根据是否有配置来决定直接添加还是弹出配置activity
     *
     * @param data
     */
    private void addAppWidget(Intent data) {
        int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

        String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET);
        d("addAppWidget", "data:" + customWidget);

        AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId);

        d("addAppWidget", "configure:" + appWidget.configure);
        if (appWidget.configure != null) {
            //有配置,弹出配置
            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
            intent.setComponent(appWidget.configure);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

            startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
        } else {
            //没有配置,直接添加
            completeAddAppWidget(data);
        }
    }


    /**
     * 3.请求添加一个新的widget:用于选取系统中的widget
     * <p>
     * 实际上系统 Launch ,选择widget之后弹出的widget列表是一个Activity,
     * <p>
     * 需要用带上Extra的,AppWidgetManager.ACTION_APPWIDGET_PICK这个Intent来启动
     * <p>
     * 这里我们用startActivityForResult()传参分类处理
     */
    private void showWidgetChooser() {
        int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
        Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
    }

    /**
     * 添加widget
     *
     * @param data
     */
    private void completeAddAppWidget(Intent data) {
        Bundle extras = data.getExtras();
        int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

        d("completeAddAppWidget", "dumping extras content=" + extras.toString());
        d("completeAddAppWidget", "appWidgetId:" + appWidgetId);
        AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);

        View hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
        frameLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, appWidgetInfo.minHeight));
        frameLayout.addView(hostView);
    }

}

效果图

App Widgets 详解三 Activity中添加App Widgets

==注意==

  1. 必须调用AppWidgetHost的startListening方法来监听appwidget的状态变化,否则添加上去的appwidget不会更新的.
  2. 需要override一个onActivityResult方法,来接收添加appwidget和appwidget的配置activity的返回值.
  3. 启动AppWidgetManager.ACTION_APPWIDGET_PICK这个Intent,必须要给列表中加上自己定义的一个选项,否则出错.

总结:

本系列Demo源码

本篇文章到此结束,欢迎关注,后续有补充的会即使更新,有问题也欢迎评论,共同成长