Android:widget 用法总结

最近做了一个widget,功能跟android自带的Picture frame功能相似,唯一不同的是,Picture frame是从SDCard中取得图片,而我做的这个widget所找的图片是从Google Picasa上面找,具体操作不是写本文的目的。

运行效果图:


图1. 选择 Picture Frame


图2. 从SDCard中找图片,它会一个一个地显示出来。


图3. 选择要剪切的图片部分


图4. 点击 Save 按钮后的界面


图5. 在上一界面上,点击 Save 按钮,就会把选择的图片加入到widget中。


图6. 换屏幕显示方向后,得到的界面。


这个跟android自带的Picture frame功能就是一样的,唯一的就是界面上有些差别,实现上也有些差别,我这个更加简单,系统的那个Picture frame功能很多。

1,widget可以有config,也可以没有,config其实就是一个activity,当运行widget时,就会最先启动这个config。
2,最重要的就是要实现AppWidgetProvider这个类,这个类其实是一个BroadcastReceiver,能接受一些系统发过来的消息等,它有几个方法,在此说明一下:

public void onReceive(Context context, Intent intent)
这个函数里面会调用相应的update, delete, enable, disabled这些方法,你可以在这个方法里处理自定义的消息。

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
当widget要更新时调用,一般在这个函数里设置widget view的数据,如果设置文本值,图片等。

public void onDeleted(Context context, int[] appWidgetIds)
当一个widget删除时,就会调用这个函数。

public void onEnabled(Context context)
如果第一次加widget,就会调用这个函数,如果android系统重启时也会调用这个方法。

public void onDisabled(Context context)
当最后一个widget被删除后,就会调用这个方法,可以在这个函数里进行一些数据清除等。

3,widget一般要每次把数据结存起来,可以存到数据库中,也可以存到share preference里面,因为在android重启后,它要能正确加载数据。

4,widget的处理流程(有config)
1)怎么启动config,也就是说,怎么说这个widget与这个config相关联?
2)config结束后,怎么把数据更新到widget里面?
首先,应该在res/xml新建一个appwidget-provider的.xml文件。这个文件就指定了这个widget的一些属性:

[html]  view plain copy
  1. <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:minHeight="146dp"  
  3.     android:minWidth="146dp"  
  4.     android:configure="com.lee.demo.activity.PictureFrameConfig">  
  5. </appwidget-provider>  

这个minHeight和minWidth有一个算法,公式是 cells * 74   - 2。
上面红色标明的就是指定它的config。

其次,在config(是一个activity)里的onCreate里面,先要得到widget的id

[java]  view plain copy
  1. this.m_appWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,  -1);  
  2. if (AppWidgetManager.INVALID_APPWIDGET_ID == m_appWidgetId)  
  3. {  
  4.       setResult(RESULT_CANCELED);  
  5.       finish();  
  6. }  

这个id后在后面用到。
在结束这个config时,要把这个id设置到intent里

[java]  view plain copy
  1. // 更新widget,说白了就是得到一个RemoteView,把其中的view设置成你要的数据。  
  2. // ...  
  3.   
  4. Intent intent = new Intent();  
  5. intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, m_appWidgetId);  
  6. setResult(resultCode, intent);  
  7. finish();  

写得有点麻烦,我直接放代码了吧,如果大家有什么不明白的,可以给我发邮件,我之前写了几个widget,基本上对widget还算明白。

PictureFrameProvider.java

[java]  view plain copy
  1. public class PictureFrameProvider extends AppWidgetProvider  
  2. {  
  3.     public static RemoteViews buildUpdateViews(Context context, int appWidgetId)  
  4.     {  
  5.         PictureDataUtility helper = new PictureDataUtility(context);  
  6.         Bitmap bitmap = helper.getPhoto(appWidgetId);  
  7.         RemoteViews views = null;  
  8.          
  9.         if (null != bitmap)  
  10.         {  
  11.             views = new RemoteViews(context.getPackageName(),  
  12.                 R.layout.picture_frame);  
  13.             views.setImageViewBitmap(R.id.photo, bitmap);  
  14.         }  
  15.          
  16.         helper.close();  
  17.          
  18.         return views;  
  19.     }  
  20.      
  21.     public static RemoteViews buildUpdateViews(Context context,  
  22.         int appWidgetId, Bitmap bitmap)  
  23.     {  
  24.         if (null == bitmap)  
  25.         {  
  26.             return null;  
  27.         }  
  28.          
  29.         PictureDataUtility helper = new PictureDataUtility(context);  
  30.         helper.setPhoto(appWidgetId, bitmap);  
  31.          
  32.         RemoteViews views = new RemoteViews(context.getPackageName(),   
  33.            R.layout.picture_frame);  
  34.         views.setImageViewBitmap(R.id.photo, bitmap);  
  35.         helper.close();  
  36.          
  37.         return views;  
  38.     }  
  39.      
  40.     public static void updateWidget(Context context,   
  41.         int appWidgetId, Bitmap bitmap)  
  42.     {  
  43.         RemoteViews views = buildUpdateViews(context, appWidgetId, bitmap);  
  44.         if (null != views)  
  45.         {  
  46.             int[] specificAppWidget = new int[] { appWidgetId };  
  47.             AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);  
  48.             appWidgetManager.updateAppWidget(specificAppWidget, views);  
  49.         }  
  50.     }  
  51.      
  52.     public void onUpdate(Context context,   
  53.         AppWidgetManager appWidgetManager, int[] appWidgetIds)  
  54.     {  
  55.         for (int appWidgetId : appWidgetIds)  
  56.         {  
  57.             int[] specificAppWidget = new int[] { appWidgetId };  
  58.             RemoteViews views = buildUpdateViews(context, appWidgetId);  
  59.             appWidgetManager.updateAppWidget(specificAppWidget, views);  
  60.         }  
  61.     }  
  62. }  

这个就是widget所对应的xml定义,它定义了widget长什么样。

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="212px"  
  4.     android:layout_height="148px"  
  5.     android:background="@drawable/appwidget_bg_land">  
  6.     <FrameLayout  
  7.            android:layout_width="fill_parent"  
  8.            android:layout_height="fill_parent"  
  9.            android:paddingLeft="17px"  
  10.            android:paddingTop="16px"  
  11.            android:paddingRight="15px"  
  12.            android:paddingBottom="15px">  
  13.         <ImageView  
  14.             android:id="@+id/photo"  
  15.             android:layout_width="fill_parent"  
  16.             android:layout_height="fill_parent"  
  17.             android:scaleType="centerCrop"  
  18.             android:cropToPadding="true" />  
  19.     </FrameLayout>                 
  20. </FrameLayout>  

PictureFrameConfig.java

[java]  view plain copy
  1. public class PictureFrameConfig extends Activity implements  
  2.     MediaSelectView.IMediaSelectCallback  
  3. {  
  4.     public static final String RETURN_DATA = "cropped_data";  
  5.     public static final int REQUEST_CROP_PICTURE = 0x02;  
  6.      
  7.     private int m_appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;  
  8.      
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState)  
  11.     {  
  12.         super.onCreate(savedInstanceState);  
  13.   
  14.         MediaSelectView mediaView = new MediaSelectView(this);  
  15.         mediaView.findMedias();  
  16.         mediaView.showButtons(false);  
  17.         mediaView.setMediaCallback(this);  
  18.          
  19.         this.setContentView(mediaView);  
  20.         this.m_appWidgetId = getIntent().getIntExtra(  
  21.             AppWidgetManager.EXTRA_APPWIDGET_ID, m_appWidgetId);  
  22.         if (AppWidgetManager.INVALID_APPWIDGET_ID == m_appWidgetId)  
  23.         {  
  24.             setResult(RESULT_CANCELED);  
  25.             finish();  
  26.         }  
  27.     }  
  28.   
  29.     @Override  
  30.     public void onCancelClick(View v)  
  31.     {  
  32.     }  
  33.   
  34.     @Override  
  35.     public void onDoneClick(View v)  
  36.     {  
  37.     }  
  38.   
  39.     @Override  
  40.     public void onItemClick(int position, View v, ImageInfo data)  
  41.     {  
  42.         Intent intent = new Intent(this, PictureFrameCropper.class);  
  43.         intent.setData(data.imageUri);  
  44.         startActivityForResult(intent, REQUEST_CROP_PICTURE);  
  45.     }  
  46.      
  47.     @Override  
  48.     protected void onActivityResult(int requestCode, int resultCode, Intent data)  
  49.     {  
  50.         if (REQUEST_CROP_PICTURE == requestCode &&  
  51.             AppWidgetManager.INVALID_APPWIDGET_ID != m_appWidgetId)  
  52.         {  
  53.             resultCode = RESULT_OK;  
  54.             Bitmap bitmap = BitmapUtility.byteArrayToBitmap(  
  55.                data.getByteArrayExtra(RETURN_DATA));  
  56.             PictureFrameProvider.updateWidget(this, m_appWidgetId, bitmap);  
  57.         }  
  58.         else  
  59.         {  
  60.             resultCode = RESULT_CANCELED;  
  61.         }  
  62.          
  63.         Intent intent = new Intent();  
  64.         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, m_appWidgetId);  
  65.         setResult(resultCode, intent);  
  66.         finish();  
  67.     }  
  68. }  

manifest定义

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.lee.demo.picture" android:versionCode="1"  
  4.     android:versionName="1.0">  
  5.     <application android:icon="@drawable/icon" android:label="@string/app_name"  
  6.         android:theme="@android:style/Theme.Light">  
  7.         <activity android:name="com.lee.demo.activity.PictureFrameConfig"  
  8.             android:label="@string/picture_list_title">  
  9.             <intent-filter>  
  10.                 <action android:name="android.intent.action.MAIN" />  
  11.                 <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>  
  12.             </intent-filter>  
  13.         </activity>  
  14.   
  15.   
  16.         <activity android:name="com.lee.demo.activity.PictureFrameCropper"  
  17.             android:label="@string/picture_crop_title">  
  18.         </activity>  
  19.   
  20.   
  21.         <receiver android:name="com.lee.demo.provider.PictureFrameProvider">  
  22.             <intent-filter>  
  23.                 <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>  
  24.             </intent-filter>  
  25.             <meta-data android:name="android.appwidget.provider"   
  26.                 android:resource="@xml/picture_widget_provider"/>  
  27.         </receiver>  
  28.     </application>  
  29.     <uses-sdk android:minSdkVersion="7" />  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值