• android4.0中实现AppWidget集合


    1.准备appwidget的初始布局和预览视图等资源

    AppWidget集合应用时,需配置两种布局文件:一个用于集合view布局显示,一个用于集合view上条目的的布局显示

    注意:要设置empty views,以便匹配集合view的空状态,且该View必须是集合View(一般可为ListViewGridViewStackViewAdapterViewFlipper)的同级View


    2.res/xml中创建AppWidgetProviderInfo文件

    根标签为appwiget-provider,其属性要包括initialLayoutpreviewImageautoAdvanceViewId 等,具体可参考后面的例子


    3.创建AppWidgetProvider的实现子类,并在清单文件里面注册引用的元数据和监听的广播action

    清单文件中,需给该子类配置如下信息:

    action android:name="android.appwidget.action.APPWIDGET_UPDATE"

    元数据:android:name="android.appwidget.provider"

    代码中,onUpdate方法中完成Widget布局到桌面上时的刷新;onReceive方法中完成接收到特定广播后的Widget刷新

    (另外,如果配置了Configure Activity还需要注册action,"android.appwidget.action.APPWIDGET_CONFIGURE"

    4.因为是集合Widget,需要创建一个继承了RemoteViewsServiceService子类,并在清单文件中注册权限,阻止其它程序自由访问Widget中的数据

    android:permission="android.permission.BIND_REMOTEVIEWS"

    代码中通过onGetViewFactory方法返回一个RemoteViewsFactory的实现类,该实现类中的onCreate()用来创建及初始化设置Widget的单个itemgetViewAt()方法用来同步数据,进行耗时的更新操作,并返回RemoteView对象。

    getViewAt方法中可完成:

    <1>将显示独立Widget条目的view item数据以fill-in intent方式填充到集合WidgetView集合中

    View集合中Chilid view不允许使用setOnClickPendingIntent的点击事件动态更新,只能通过setOnClickFillInIntent来实现,

    即先设置好集合viewpending intent template点击事件模版,然后,将独立的chilid view条目的the fill-in Intent意图事件填充进来。

    <2>进行耗时的处理图片和获取网络数据操作,并同步刷新Widget的显示内容。

    RemoteViewsFactory的实现类中还有一个onDataSetChanged方法,也可进行耗时的处理图片和获取网络数据操作,但他可以保持Widget的当前状态,直到我们显示调用AppWidgetManager notifyAppWidgetViewDataChanged才会触发


    参考:ExampleStackViewAppWidgets

    本例主要参考http://developer.android.com/resources/samples/StackWidget/index.html

    在其基础上略有改进

    appwidget_providerinfo.xml

    <?xml version="1.0" encoding="utf-8"?>

    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

    android:autoAdvanceViewId="@id/statck_view"

    android:initialLayout="@layout/widget_layout"

    android:minHeight="74dp"

    android:minWidth="290dp"

    android:previewImage="@drawable/doraemon"

    android:updatePeriodMillis="3600000"

    android:resizeMode="vertical">

    </appwidget-provider>


    StackViewAppWidgetService.java

    /**

    * 实现了给StackViewImageView适配背景图片

    * @author wgyang

    *

    */

    public class StackViewAppWidgetService extends RemoteViewsService {

    @Override

    public RemoteViewsFactory onGetViewFactory(Intent intent) {

    return new ViewFlipperRemoteViewsFactory(this.getApplicationContext(),

    intent);

    }


    }

    class ViewFlipperRemoteViewsFactory implements

    RemoteViewsService.RemoteViewsFactory {

    int[] images = { R.drawable.doraemon, R.drawable.baidu, R.drawable.bing,

    R.drawable.google };

    //int[] colors = { Color.BLUE, Color.RED, Color.GRAY, Color.GREEN };

    private static final int mCount = 4;

    private List<ImageView> mImageViews = new ArrayList<ImageView>();

    private Context mContext;

    private static ImageView mImageView;


    public ViewFlipperRemoteViewsFactory(Context context, Intent intent) {

    mContext = context;

    }

    public void onCreate() {

    // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,

    // for example downloading or creating content etc, should be deferred to onDataSetChanged()

    // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.

    // 因不是很耗时,可放在这里

    //在循环里控制显示独立Widget条目的界面信息

    for (int i = 0; i < mCount; ++i) {

    mImageView = new ImageView(mContext);

    //mImageView.setBackgroundColor(colors[i]);

    //mImageView.setImageResource(images[i]);

    mImageViews.add(mImageView);

    }

    // We sleep for 3 seconds here to show how the empty view appears in the interim.

    // The empty view is set in the StackWidgetProvider and should be a sibling of the

    // collection view.

    }

    public RemoteViews getViewAt(int position) {

    // position will always range from 0 to getCount() - 1.

    // We construct a remote views item based on our widget item xml file, and set the

    // text based on the position.

    //通过Remoteviewview item上设置要显示内容

    RemoteViews rv = new RemoteViews(mContext.getPackageName(),

    R.layout.widget_item);

    // rv.setTextViewText(R.id.widget_item,

    // mWidgetItems.get(position).text);

    //rv.setImageViewResource(R.id.widget_item, mImageViews.get(position)

    // .getBackground().getLevel());

    //注意要将单个的widget条目信息设置进rv中,不然刷新界面不成功的

    rv.setImageViewBitmap(R.id.widget_item, BitmapFactory.decodeResource(

    mContext.getResources(), images[position]));

    // Next, we set a fill-intent which will be used to fill-in the pending intent template

    // which is set on the collection view in StackWidgetProvider.

    //item的位置信息设置到fillintent

    Bundle extras = new Bundle();

    extras.putInt(StackViewAppWidgetProvider.EXTRA_ITEM, position);

    //设置fill-intent以填充Pending intent 模版

    Intent fillInIntent = new Intent();

    fillInIntent.putExtras(extras);

    rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);

    // You can do heaving lifting in here, synchronously. For example, if you need to

    // process an image, fetch something from the network, etc., it is ok to do it here,

    // synchronously. A loading view will show up in lieu of the actual contents in the

    // interim.

    //其它耗时操作可在这里完成

    return rv;

    }

    public int getCount() {

    return mCount;

    }

    public RemoteViews getLoadingView() {

    // You can create a custom loading view (for instance when getViewAt() is slow.) If you

    // return null here, you will get the default loading view.

    return null;

    }

    public int getViewTypeCount() {

    return 1;//注意下,初始是0,改变与否不影响

    }


    public long getItemId(int position) {

    return position;

    }

    public boolean hasStableIds() {

    return true;//注意下,原来是false,改变与否不影响

    }

    public void onDataSetChanged() {

    // This is triggered when you call AppWidgetManager notifyAppWidgetViewDataChanged

    // on the collection view corresponding to this factory. You can do heaving lifting in

    // here, synchronously. For example, if you need to process an image, fetch something

    // from the network, etc., it is ok to do it here, synchronously. The widget will remain

    // in its current state while work is being done here, so you don't need to worry about

    // locking up the widget.

    //耗时操作可放在这里,可显式触发

    }

    public void onDestroy() {

    // In onDestroy() you should tear down anything that was setup for your data source,

    // eg. cursors, connections, etc.

    mImageViews.clear();

    }

    }



    StackViewAppWidgetProvider.java

    /**

    * StackView更新图片

    * 定时接收广播,自动刷新view,另外监听点击事件,弹土司消息反馈点击的是哪一个条目

    * @author wgyang

    *

    */

    public class StackViewAppWidgetProvider extends AppWidgetProvider {

    public static final String TOAST_ACTION = "com.lenove.widgetcollection.TOAST_ACTION";

    public static final String EXTRA_ITEM = "com.lenove.widgetcollection.EXTRA_ITEM";

    @Override

    public void onReceive(Context context, Intent intent) {

    if (intent.getAction().equals(TOAST_ACTION)) {

    int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);

     

    Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show();

    }

    super.onReceive(context, intent);

    }

    // 完成Widget布局到桌面上时的刷新

    @Override

    public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {

    // update each of the widgets with the remote adapter

    //遍历每个appWidgetId

    for (int i = 0; i < appWidgetIds.length; ++i) {

     


    // Here we setup the intent which points to the StackViewService which will

    // provide the views for this collection.

    //指定启动到RemoteViewstServiceIntent

    Intent intent = new Intent(context, StackViewAppWidgetService.class);

    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);

    // When intents are compared, the extras are ignored, so we need to embed the extras

    // into the data so that the extras will not be ignored.

    // 嵌入数据到intent,以避免intent中的数据被忽略掉

    intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

    //借助RemoteView传递信息

    RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

    //注意,设置适配器

    rv.setRemoteAdapter(appWidgetIds[i], R.id.statck_view, intent);

    // The empty view is displayed when the collection has no items. It should be a sibling

    // of the collection view.

    //注意,设置空状态

    rv.setEmptyView(R.id.statck_view, R.id.empty_view);

    // Here we setup the a pending intent template. Individuals items of a collection

    // cannot setup their own pending intents, instead, the collection as a whole can

    // setup a pending intent template, and the individual items can set a fillInIntent

    // to create unique before on an item to item basis.

    //设置封装了操作信息的intnent--最终放到pendingIntentTemplate

    Intent toastIntent = new Intent(context, StackViewAppWidgetProvider.class);

    toastIntent.setAction(StackViewAppWidgetProvider.TOAST_ACTION);

    toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);

    intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

    //设置延迟意图模版PendingIntentTemplete,加载到RemoteViews,最后由AppWidgetManager更新

    PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,

    PendingIntent.FLAG_UPDATE_CURRENT);

    rv.setPendingIntentTemplate(R.id.statck_view, toastPendingIntent);

    //如果有耗时的操作应该启动应该服务Service去完成

    appWidgetManager.updateAppWidget(appWidgetIds[i], rv);

    }

    super.onUpdate(context, appWidgetManager, appWidgetIds);

    }


    }

     

    摘自:http://wenku.baidu.com/view/aab74fa4b0717fd5360cdc4a.html

  • 相关阅读:
    unity3d热更新插件uLua学习整理
    结合axios对项目中的api请求进行封装
    移动端适配剖析
    vscode如何调试node项目(给node项目打断点)
    mac上使用cnpm搭建npm私有仓库,并上传/下载私有npm包
    前端常见的兼容性问题--web端和移动端
    react树形选择组(支持:单选,多选,全选)
    MongoDB 与 Mysql 的对比
    使用div 的 contenteditable属性,实现输入编辑,输入 "#" 出现下拉选择
    前端单元测试,以及给现有的vue项目添加jest + Vue Test Utils的配置
  • 原文地址:https://www.cnblogs.com/veins/p/3840404.html
Copyright © 2020-2023  润新知