转载请标明出处:http://blog.csdn.net/sk719887916/article/details/47027263
不少开发项目中都会有widget功能,别小瞧了它,他也是android的七大组件之一,对widget陌生的朋友可以阅读下我的上篇文章< Android Widget工作原理详解(一)> 今天我们就实现一个可以滑动的widet,熟悉下一个普通widget的开发。
 @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        // 获取Widget的组件名
        ComponentName thisWidget = new ComponentName(context,
                MyAppListWidgetProvider.class);
        // 创建一个RemoteView
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.my_widget_layout);
        // 把这个Widget绑定到RemoteViewsService
        Intent intent = new Intent(context, MyRemoteViewsService.class);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[0]);
        // 设置适配器
        remoteViews.setRemoteAdapter(R.id.widget_list, intent);
        // 设置当显示的widget_list为空显示的View
        remoteViews.setEmptyView(R.id.widget_list, R.layout.none_data);
        // 点击列表触发事件
        Intent clickIntent = new Intent(context, MyAppListWidgetProvider.class);
        // 设置Action,方便在onReceive中区别点击事件
        clickIntent.setAction(clickAction);
        clickIntent.setData(Uri.parse(clickIntent.toUri(Intent.URI_INTENT_SCHEME)));
        PendingIntent pendingIntentTemplate = PendingIntent.getBroadcast(
                context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setPendingIntentTemplate(R.id.widget_list,
                pendingIntentTemplate);
        // 刷新按钮
        final Intent refreshIntent = new Intent(context,
                MyAppListWidgetProvider.class);
        refreshIntent.setAction("refresh");
        final PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(
                context, 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.button_refresh,
                refreshPendingIntent);
        // 更新Wdiget
        appWidgetManager.updateAppWidget(thisWidget, remoteViews);
    }       <!-- Widget必须添加到manifest文件中,和Broadcaset Receiver一样使用“receiver”标签 -->
        <receiver android:name=".MyAppListWidgetProvider" >
            <!-- 此处设置Wdiget更新动作 -->
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <!-- 此处设置Widget的描述资源res/xml/my_widget.xml -->
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_info" 
               >
            </meta-data>
        </receiver>/**
     * 接收Intent
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
     
        String action = intent.getAction();
        if (action.equals("refresh")) {
            // 刷新Widget
            final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
            final ComponentName cn = new ComponentName(context,
                    MyAppListWidgetProvider.class);
            MyRemoteViewsFactory.mList.add("音乐"+i);
      
            // 这句话会调用RemoteViewSerivce中RemoteViewsFactory的onDataSetChanged()方法。
            mgr.notifyAppWidgetViewDataChanged(mgr.getAppWidgetIds(cn),
                    R.id.widget_list);
           
        } else if (action.equals(clickAction)) {
            // 单击Wdiget中ListView的某一项会显示一个Toast提示。
            Toast.makeText(context, intent.getStringExtra("content"),
                    Toast.LENGTH_SHORT).show();
        }
        i=i+1;
    } @Override
    public void onEnabled(Context context) {
    	// TODO Auto-generated method stub
    	super.onEnabled(context);
    	
    	
        Toast.makeText(context, "用户将widget添加桌面了",
                Toast.LENGTH_SHORT).show();
    }   @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
    	// TODO Auto-generated method stub。
        Toast.makeText(context, "用户将widget从桌面移除了",
                Toast.LENGTH_SHORT).show();
    	super.onDeleted(context, appWidgetIds);
    }public class MyRemoteViewsFactory implements RemoteViewsFactory {
	 private final Context mContext;
	    public static List<String> mList = new ArrayList<String>();
	    /*
	     * 构造函数
	     */
	    public MyRemoteViewsFactory(Context context, Intent intent) {
	        mContext = context;
	    }
	    /*
	     * MyRemoteViewsFactory调用时执行,这个方法执行时间超过20秒回报错。
	     * 如果耗时长的任务应该在onDataSetChanged或者getViewAt中处理
	     */
	    @Override
	    public void onCreate() {
	        // 需要显示的数据
	        mList.add("");
	        for (int i = 0; i < 5; i++) {
	        	  mList.add("item"+ i);
			}
	      
	       
	    }
	    /*
	     * 当调用notifyAppWidgetViewDataChanged方法时,触发这个方法
	     * 例如:MyRemoteViewsFactory.notifyAppWidgetViewDataChanged();
	     */
	    @Override
	    public void onDataSetChanged() {
	    
	    }
	    /*
	     * 这个方法不用多说了把,这里写清理资源,释放内存的操作
	     */
	    @Override
	    public void onDestroy() {
	        mList.clear();
	    }
	    /*
	     * 返回集合数量
	     */
	    @Override
	    public int getCount() {
	        return mList.size();
	    }
	    /*
	     * 创建并且填充,在指定索引位置显示的View,这个和BaseAdapter的getView类似
	     */
	    @Override
	    public RemoteViews getViewAt(int position) {
	        if (position < 0 || position >= mList.size())
	            return null;
	        String content = mList.get(position);
	        // 创建在当前索引位置要显示的View
	        final RemoteViews rv = new RemoteViews(mContext.getPackageName(),
	                R.layout.my_widget_layout_item);
	        // 设置要显示的内容
	        rv.setTextViewText(R.id.widget_list_item_tv, content);
	        // 填充Intent,填充在AppWdigetProvider中创建的PendingIntent
	        Intent intent = new Intent();
	        // 传入点击行的数据
	        intent.putExtra("content", content);
	        rv.setOnClickFillInIntent(R.id.widget_list_item_tv, intent);
	        return rv;
	    }
	    /*
	     * 显示一个"加载"View。返回null的时候将使用默认的View
	     */
	    @Override
	    public RemoteViews getLoadingView() {
	        return null;
	    }
	    /*
	     * 不同View定义的数量。默认为1(本人一直在使用默认值)
	     */
	    @Override
	    public int getViewTypeCount() {
	        return 1;
	    }
	    /*
	     * 返回当前索引的。
	     */
	    @Override
	    public long getItemId(int position) {
	        return position;
	    }
	    /*
	     * 如果每个项提供的ID是稳定的,即她们不会在运行时改变,就返回true(没用过。。。)
	     */
	    @Override
	    public boolean hasStableIds() {
	        return true;
	    }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MyRemoteViewsService extends RemoteViewsService {
	@Override
	public RemoteViewsFactory onGetViewFactory(Intent intent) {
		
		   return new MyRemoteViewsFactory(this.getApplicationContext(), intent);
	}
}
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/my_widget_layout"
    android:minHeight="120dp"
    android:minWidth="280dp"
    android:previewImage="@drawable/ic_launcher"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="0" >
    <!--
        sdk1.5之后updatePeriodMillis已失效,置为0,循环执行自行在代码中实现。
        至于其他属性可以查一下。在其他随笔中我也给出了
    -->
</appwidget-provider><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@android:color/white"
    android:orientation="vertical" >
    <Button
        android:id="@+id/button_refresh"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
         android:background="@drawable/lite_widget_item_choosed_background_icon"	
        android:textColor="@android:color/white"
        android:layout_marginTop="2dp"
        android:text="刷新" />
    
      
    <ListView
        android:id="@+id/widget_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:cacheColorHint="#00000000"
        android:scrollbars="none" />
    <!-- 此处的ListView 可以换成StackView或者GridView -->
</LinearLayout>版权声明:本文为博主原创文章,请尊重原创,转载请标明地址。
原文地址:http://blog.csdn.net/sk719887916/article/details/47027263