Android 4.0 新增的显示数据集的桌面控件

setRemoteAdapter (int viewId, Intent intent):该方法可以使用 Intent 更新 RemoteViews 中viewId 对应的组件。

上面方法的 Intent 参数应该封装一个 RemoteViewsService 参数,RemoteViewsService 虽然继承了 Service 组件,但它的主要作用是为 RemoteViews 中 viewId 对应的组件提供列表项。

由于Intent参数负责提供列表项,因此viewId参数对应的组件可以是ListView、GridView、StackView 和 AdapterViewFlipper 等,这些组件都是 AdapterView 的子类,由此可见RemoteViewsService 负责提供的对象,应该是一个类似于 Adapter 的对象。

RemoteViewsService 通常用于被继承,继承该基类时需要重写它的 onGetViewFactory()方 法 , 该 方 法 就 需 要 返 回 一 个 类 似 于 Adapterr 对 象 —— 但 不 是 Adapter , 而 是RemoteViewsFactory 对象,RemoteViewsFactory 的功能完全类似于 Adapter。

StackViewWidget实现如下:

StackWidgetService.java

package org.crazyit.desktop;



import android.content.Context;

import android.content.Intent;

import android.widget.RemoteViews;

import android.widget.RemoteViewsService;



/**

 * Description:

 * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>

 * <br/>Copyright (C), 2001-2014, Yeeku.H.Lee

 * <br/>This program is protected by copyright laws.

 * <br/>Program Name:

 * <br/>Date:

 * @author Yeeku.H.Lee [email protected]

 * @version 1.0

 */

public class StackWidgetService extends RemoteViewsService

{

    // 重写该方法,该方法返回一个RemoteViewsFactory对象。

    // RemoteViewsFactory对象的的作用类似于Adapter,

    // 它负责为RemoteView中指定组件提供多个列表项。

    @Override

    public RemoteViewsFactory onGetViewFactory(Intent intent)

    {

        return new StackRemoteViewsFactory(this.getApplicationContext(),

            intent);  //

    }

    class StackRemoteViewsFactory implements

    RemoteViewsService.RemoteViewsFactory

    {

        // 定义一个数组来保存该组件生成的多个列表项

        private int[] items = null;

        private Context mContext;

        public StackRemoteViewsFactory(Context context, Intent intent)

        {

            mContext = context;

        }

        @Override

        public void onCreate()

        {

            // 初始化items数组

            items = new int[] { R.drawable.bomb5, R.drawable.bomb6,

                R.drawable.bomb7, R.drawable.bomb8, R.drawable.bomb9,

                R.drawable.bomb10, R.drawable.bomb11, R.drawable.bomb12,

                R.drawable.bomb13, R.drawable.bomb14, R.drawable.bomb15,

                R.drawable.bomb16

            };

        }

        @Override

        public void onDestroy()

        {

            items = null;

        }

        // 该方法的返回值控制该对象包含多少个列表项

        @Override

        public int getCount()

        {

            return items.length;

        }

        // 该方法的返回值控制各位置所显示的RemoteViews

        @Override

        public RemoteViews getViewAt(int position)

        {

            // 创建RemoteViews对象,加载/res/layout目录下widget_item.xml文件

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

                R.layout.widget_item);

            // 更新widget_item.xml布局文件中的widget_item组件

            rv.setImageViewResource(R.id.widget_item,

                items[position]);

            // 创建Intent、用于传递数据

            Intent fillInIntent = new Intent();

            fillInIntent.putExtra(StackWidgetProvider.EXTRA_ITEM, position);

            // 设置当单击该RemoteViews时传递fillInIntent包含的数据

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

            // 此处使用让线程暂停0.5秒来模拟加载该组件

            try

            {

                System.out.println("加载【" + position + "】位置的组件");

                Thread.sleep(500);

            }

            catch (InterruptedException e)

            {

                e.printStackTrace();

            }

            return rv;

        }

        @Override

        public RemoteViews getLoadingView()

        {

            return null;

        }

        @Override

        public int getViewTypeCount()

        {

            return 1;

        }

        @Override

        public long getItemId(int position)

        {

            return position;

        }

        @Override

        public boolean hasStableIds()

        {

            return true;

        }

        @Override

        public void onDataSetChanged()

        {

        }

    }    

}

widget_item.xml

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

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/widget_item"

    android:layout_width="120dp"

    android:layout_height="120dp"

    android:gravity="center"/>

StackWidgetProvider.java

package org.crazyit.desktop;



import android.app.PendingIntent;

import android.appwidget.AppWidgetManager;

import android.appwidget.AppWidgetProvider;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.widget.RemoteViews;

import android.widget.Toast;



/**

 * Description:

 * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>

 * <br/>Copyright (C), 2001-2014, Yeeku.H.Lee

 * <br/>This program is protected by copyright laws.

 * <br/>Program Name:

 * <br/>Date:

 * @author Yeeku.H.Lee [email protected]

 * @version 1.0

 */

public class StackWidgetProvider extends AppWidgetProvider

{

    public static final String TOAST_ACTION

        = "org.crazyit.desktop.TOAST_ACTION";

    public static final String EXTRA_ITEM 

        = "org.crazyit.desktop.EXTRA_ITEM";



    @Override

    public void onUpdate(Context context,

        AppWidgetManager appWidgetManager, int[] appWidgetIds)

    {

        // 创建RemoteViews对象,加载/res/layout目录下的widget_layout.xml文件

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

            R.layout.widget_layout);

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

        // 使用intent更新rv中stack_view组件(StackView)

        rv.setRemoteAdapter(R.id.stack_view, intent);  //// 设置当StackWidgetService提供的列表项为空时,直接显示empty_view组件

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

        // 创建启动StackWidgetProvider组件(作为BroadcastReceiver)的Intent

        Intent toastIntent = new Intent(context,

            StackWidgetProvider.class);

        // 为该Intent设置Action属性

        toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);

        // 将Intent包装成PendingIntent

        PendingIntent toastPendingIntent = PendingIntent

            .getBroadcast(context, 0, toastIntent,

                PendingIntent.FLAG_UPDATE_CURRENT);

        // 将PendingIntent与stack_view进行关联

        rv.setPendingIntentTemplate(R.id.stack_view,

            toastPendingIntent);

        // 使用AppWidgetManager通过RemteViews更新AppWidgetProvider

        appWidgetManager.updateAppWidget(

            new ComponentName(context, StackWidgetProvider.class), rv); //

        super.onUpdate(context, appWidgetManager, appWidgetIds);

    }

    @Override

    public void onDeleted(Context context, int[] appWidgetIds)

    {

        super.onDeleted(context, appWidgetIds);

    }



    @Override

    public void onDisabled(Context context)

    {

        super.onDisabled(context);

    }



    @Override

    public void onEnabled(Context context)

    {

        super.onEnabled(context);

    }

    // 重写该方法,将该组件当成BroadcastReceiver使用

    @Override

    public void onReceive(Context context, Intent intent)

    {

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

        {

            // 获取Intent中的数据

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

            // 显示Toast提示

            Toast.makeText(context, "点击第【" + viewIndex + "】个列表项",

                Toast.LENGTH_SHORT).show();

        }

        super.onReceive(context, intent);

    }    

}

widget_layout.xml

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

<FrameLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:layout_margin="8dp">

    <StackView

        android:id="@+id/stack_view"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:gravity="center"

        android:loopViews="true" />

    <TextView

        android:id="@+id/empty_view"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:gravity="center"

        android:background="#ff0f"

        android:textColor="#ffffff"

        android:textStyle="bold"

        android:text="@string/no_item"

        android:textSize="20sp" />

</FrameLayout>

Manifest.xml

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

<manifest

    xmlns:android="http://schemas.android.com/apk/res/android"

    package="org.crazyit.desktop"

    android:versionCode="1"

    android:versionName="1.0">

    <uses-sdk

        android:minSdkVersion="14"

        android:targetSdkVersion="17" />

<application

    android:allowBackup="true"

    android:label="@string/app_name">

    <!-- 配置AppWidgetProvider,即配置桌面控件 -->

    <receiver android:name=".StackWidgetProvider">

        <!-- 通过该intent-filter指定该Receiver作为桌面控件 -->

        <intent-filter>

            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

        </intent-filter>

        <!-- 为桌面控件指定meta-data -->

        <meta-data

            android:name="android.appwidget.provider"

            android:resource="@xml/stackwidgetinfo" />

    </receiver>

    <!-- 配置RemoteViewsService

    必须指定权限为android.permission.BIND_REMOTEVIEWS

     -->

    <service

        android:name=".StackWidgetService"

        android:permission="android.permission.BIND_REMOTEVIEWS"

        android:exported="false" />

</application>

</manifest>

stackwidgetinfo.xml

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

<appwidget-provider

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:minWidth="110dp"

    android:minHeight="110dp"

    android:updatePeriodMillis="3600000"

    android:previewImage="@drawable/ic_launcher"

    android:initialLayout="@layout/widget_layout"

    android:resizeMode="horizontal|vertical"

    android:autoAdvanceViewId="@id/stack_view">

</appwidget-provider>

截图:

image

你可能感兴趣的:(android 4.0)