原文作者:  Gagandeep Singh               在早期版本的Android,应用小部件只能显示文本框和图片等控件。但是,如果我们要显示控件项目列表怎么办?例如,显示整个下周的温度信息列表。Android 3.0中引入了集合小部件(Collection Widget),以提供更好的体验。支持ListView,GridView和StackView布局。        今天,我将帮助您了解集合小部件的工作原理。我们将为 (to-do app)待办事宜应用程序构建一个应用程序小部件。集合小部件将用于显示待办事宜的列表。        我假设你已经知道如何制作一个基本的应用程序小部件。如果没有,请参考 这篇文章 ,当您准备好制作自己的集合小部件时再看这篇文章。         入门         请 在这里下载初始项目代码, 该代码已经实现了一个基本的小部件,我们将在项目中创建一个集合部件。       一个基本的小部件显示待处理事宜的数量,而集合部件将显示完整的列表。 要制作集合小部件,除了基本组件之外,还需要两个主要组件:

   RemoteViewsService

   RemoteViewsFactory

   首先 我们来了解这些组件的作用。

      

    运用 RemoteViewsFactory

      

   RemoteViewsFactory用来

在窗口小部件的上下文中提供适配器。用于将集合(例如ListView项或GridView项)与数据集进行连接。

我们将这个类添加到我们的项目中。创建一个新的Java类,将其命名为

MyWidgetRemoteViewsFactory ,并将其实现 RemoteViewsService.RemoteViewsFactory 。       

查看源文件  复制代码

public class MyWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {


    private Context mContext;

    private Cursor mCursor;


    public MyWidgetRemoteViewsFactory(Context applicationContext, Intent intent) {

        mContext = applicationContext;

    }


    @Override

    public void onCreate() {


    }


    @Override

    public void onDataSetChanged() {


        if (mCursor != null) {

            mCursor.close();

        }


        final long identityToken = Binder.clearCallingIdentity();

        Uri uri = Contract.PATH_TODOS_URI;

        mCursor = mContext.getContentResolver().query(uri,

                null,

                null,

                null,

                Contract._ID + " DESC");


        Binder.restoreCallingIdentity(identityToken);


    }


    @Override

    public void onDestroy() {

        if (mCursor != null) {

            mCursor.close();

        }

    }


    @Override

    public int getCount() {

        return mCursor == null ? 0 : mCursor.getCount();

    }


    @Override

    public RemoteViews getViewAt(int position) {

        if (position == AdapterView.INVALID_POSITION ||

                mCursor == null || !mCursor.moveToPosition(position)) {

            return null;

        }


        RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.collection_widget_list_item);

        rv.setTextViewText(.widgetItemTaskNameLabel, mCursor.getString(1));


        return rv;

    }


    @Override

    public RemoteViews getLoadingView() {

        return null;

    }


    @Override

    public int getViewTypeCount() {

        return 1;

    }


    @Override

    public long getItemId(int position) {

        return mCursor.moveToPosition(position) ? mCursor.getLong(0) : position;

    }


    @Override

    public boolean hasStableIds() {

        return true;

    }


}

     在上面的代码中,

MyWidgetRemoteViewsFactory  重写了RemoteViewFactory类中的一些方法。

  • onCreate 当第一次创建appwidget时会调用它。
  • onDataSetChanged 只要appwidget被更新就会调用。
  • getCount返回光标中的记录数。(在我们的例子中,就是需要在应用程序小部件中显示的任务项目的数量)
  • getViewAt处理所有的处理工作。它返回一个RemoteViews对象,在我们的例子中是单个列表项。
  • getViewTypeCount返回ListView 中views的类型个数,在我们的例子中,我们在每个ListView项目中都是相同的视图类型,所以我们return 1在那里。