zoukankan      html  css  js  c++  java
  • Android基础 Widget

    先来看下效果图. 这是仿三星FM收音机的一个widget.



    1. 首先在widget创建一个布局文件: layout/widget.xml.

    2. 在xml中创建xml/radioinfo.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:initialLayout="@layout/widget"
        android:minHeight="50.0dip"
        android:minWidth="300.0dip"
        android:previewImage="@drawable/fm_radio_widget_preview"
        android:resizeMode="vertical" />

    属性解释: android:initialLayout="@layout/widget"   : 指定widget的布局文件

      android:previewImage="@drawable/fm_radio_widget_preview"  指定widget在手机小部件中的缩略图.


    3.  创建一个继承AppWidgetProvider类FMRadioWidgetProvider.java, 并实现onUpdate , onReceive ,这两个函数.

           3.1 AppWidgetProvider解释:  这个类其实是一个广播接收器, 当widget被拖放到桌面的时候会首先调用onUpdate(Context context, AppWidgetManager appWidgetManager,
    int[] appWidgetIds)函数. 所以 , 一般在这个函数中做初始化操作.

    3.2 为按钮添加事件: 

    Intent intent = new Intent(FMRadioService.ACTION_FM_NEXT);
            intent.setClass(context, FMRadioService.class);
            pIntent = PendingIntent.getService(context, 0, intent, 0);
            remoteViews.setOnClickPendingIntent(R.id.ic_arrow_right, pIntent);


     当点击这个这个按钮的时候, 会发送一个Intent并FMRadioService类.  

      这种方式绑定的事件只能适用于单个View.  对于像ListView,  GridView这样的集合的item要绑定事件的话不适用. 这点后面讲到.

    3.3 为组件设置相关属性, 例如给TextView设置文本:

    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
    	remoteViews.setTextViewText(R.id.txt_frequency, String.valueOf(freq));


    最后: 要记得updateWidget一下: AppWidgetManager.getInstance(context).updateAppWidget(appWidgetIds, remoteViews); 一开始我就忘记了update , 导致widget没有显示 任何东西.

    3.4 为GridView/ListView绑定数据集: widget中的FM电台列表是一个GridView. 那么如何为GridView设置数据集呢.

    Intent intent = new Intent(context , FMRadioWidgetService.class);
    	intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    	intent.setData(FMRadioStation.Station.CONTENT_URI);
    	remoteViews.setRemoteAdapter(appWidgetId, R.id.widget_gridView, intent);


    设置数据集需要提供一个远程适配器. 适配器是一个RemoteViewsService类型的对象. 该类实现一个onGetViewFactory(Intent intent)函数:

    public class FMRadioWidgetService extends RemoteViewsService {
    
    		private final String LOGTAG = "FMRadioWidgetService"  ; 
    		private final boolean ISLOG = false ;
    	
    		@Override
    		public RemoteViewsFactory onGetViewFactory(Intent intent) {
    		
    			if(ISLOG)Log.d(LOGTAG , " FMRadioWidgetService::[onGetViewFactory ] intent = "+intent);
    		
    			return new FMRadioRemoteViewsFactory(getApplicationContext() , intent);
    		}
    	
    	}


    FMRadioRemoteViewsFactory才是一个正在的adapter. 该类实现RemoteViewsFactory接口, 并实现了onDataSetChanged() 和 getViewAt(int position)函数,

    此处getViewAt(int position)的实现类似我们传统Adapter的bindView()函数. 然后在onDataSetChanged() 一般会从数据库读取数据.

    @Override
    	public RemoteViews getViewAt(int position) {
    
    		RemoteViews rv = new RemoteViews(mContext.getPackageName() , R.layout.widget_item);
    		...
    		HashMap<String, Object> map = mlistStations.get(position);
    		rv.setTextViewText(R.id.widget_gv_txt_itme, freqStr);
    		...	
    		Intent fillInIntent = new Intent();
    		Bundle extras = new Bundle();
    		
    		extras.putInt(FMRadioAppWidgetProvider.EXTRA_SORT, position);
    		fillInIntent.putExtras(extras);
    		
    		// Make it possible to distinguish the individual on-click
    		// action of a given item
          
    		rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
    	
    		return rv;
    	}
    
    
    	@Override
    	public void onDataSetChanged() {
    	
    		queryFMradioStation();
    	
    	}


    在getViewAt()中为GridView的每一个item设置click事件:

    Intent fillInIntent = new Intent();
    Bundle extras = new Bundle();
     
    extras.putInt(FMRadioAppWidgetProvider.EXTRA_SORT, position);
    fillInIntent.putExtras(extras);

    // Make it possible to distinguish the individual on-click
    // action of a given item
          
    rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);

    而该处的intent要与FMRadioWidgetProvider.java的onUpdate函数中的:

    // Set the action for the intent.
                // When the user touches a particular view, it will have the effect of
               // broadcasting TOAST_ACTION.
    itemClcikIntent.setAction(FMRadioAppWidgetProvider.ACTION_CLICK);
    itemClcikIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
                PendingIntent itemPendingIntent = PendingIntent.getBroadcast(context, 0, itemClcikIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
               remoteViews.setPendingIntentTemplate(R.id.widget_gridView, itemPendingIntent);

    这两处最终合成一个Intent. 当点击每一个item的时候, 会发送一个ACTION_CLICK的广播, 并且在FMRadioAppWidgetProvide接收广播后, 在onReceive中进行处理.

    整个widget大概基本完成.  

  • 相关阅读:
    通过IP获取所在城市
    一次完整的HTTP请求过程
    Array.prototype.slice.call(arguments)
    移动web资源整理
    Null 和 Undefined
    JS正则表达式
    JavaScript和JSP的区别?
    JS判断图片上传时文件大小和图片尺寸
    JavaScript中的callee与caller的区别
    php结合redis实现高并发下的抢购、秒杀功能
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3106682.html
Copyright © 2011-2022 走看看