zoukankan      html  css  js  c++  java
  • Android4.0中AppWidget的一些新玩意体验---RemoteViewsService

    最近要把之前做的2.3上面的一些程序移植到4.0上面来,  几乎所有的AppWidget都是我一手操办, 所以这个玩意都是我弄.

    我把Android2.3的代码直接拷到4.0的环境下面, 编译然后Push,  直接可以跑, 这是木有问题的.  但是我发现4.0上面有一些新东东是之前2.3上面没有的,

    我也读了下官方的文档, 做了些demo, 这里总结给大家, 在以后需要做AppWidget的时候可以得心应手.

    1: 应用列表中的预览图

    如果你不想你的Widget在应用列表里面显示成那个丑机器人图片的话, 就需要在<appwidget-provider>中设置previewImage属性,例如:

    [html] view plaincopy
     
    1. <appwidget-provider   
    2.     android:previewImage="@drawable/widget_preview"  
    3. />  


    2. Widget可以resize

    这个我先没注意到, 玩开发板的时候不小心把系统中带的日历的Widget拖出来,想删没有删掉, 发现边上出来一圈蓝边,于是乎想到是不是可以resize大小呢.?结果一试还真是可以,就翻日历源码的Widget和相应的xml文件,发现在<appwidget-provider>中设置了resizeMode属性, 可以设置让用户横向拉, 纵向拉.  设置minResizeWidth和minResizeHeight可以根据需要指定每次缩放的大小(一般设成一格宽, 当然对于集合来说这个要根据你Widget每个元素的大小,一般遵循的规则是拉伸大小为Widget里面每个元素的大小. 例如我看到BookMarket,他的每个元素是占一行两列,所以此时你设置拉伸大小就要注意了, 最好也设置成每次横向两列, 纵向一行就行了 ).   例如

    [java] view plaincopy
     
    1. <!--需要两个方向都可以拉的话,就把他们或起来,android里面很多都是这么做的 -->  
    2. <appwidget-provider  
    3.   android:resizeMode="horizontal|vertical"  
    4.   android:minResizeWidth="146dip"  
    5.   android:minResizeHeight="72dip"  
    6. />  

    以上72和146是怎么计算出来的这个不深说了, 文档上是这么说得.

    3.支持很多集合控件

    这个事非常让我兴奋的阿, 以前看到我Htc的机子上面Widget有集合控件,支持手势, 但是如果不定制RemoteViews是没办法实现的.

    Gallery2中的Widget就是拿StackView去做的.  于是我参照了下Gallery2的源码和官方文档,了解了Widget中使用集合控件的方法.

    集合是通过一个RemoteViewService去做的, 然后要创建一个RemoteViewsFactory, 这个接口里面的一些方法下面我会一一解释.

    不多说.直接上我写的demo的代码,拿ListView做的,其他集合控件都差不多的使用.

    widget_provider.xml

    [html] view plaincopy
     
    1. <?xml version="1.0" encoding="utf-8" ?>   
    2.   <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"   
    3.         android:minHeight="220dip"   
    4.         android:minWidth="220dip"   
    5.         android:updatePeriodMillis="0"   
    6.         android:initialLayout="@layout/main" />   


    main.xml

    [html] view plaincopy
     
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:layout_width="fill_parent"  
    4.     android:layout_height="fill_parent"  
    5.     android:orientation="vertical" >  
    6.     <ListView  
    7.        android:layout_width="fill_parent"  
    8.        android:layout_height="fill_parent"   
    9.        android:id="@+id/list_data"  
    10.          />  
    11.       
    12.       
    13. </LinearLayout>  

    list_item.xml

    [java] view plaincopy
     
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:orientation="horizontal"  
    6.     android:id="@+id/item_layout" >  
    7.     <TextView   
    8.         android:layout_width="wrap_content"  
    9.         android:layout_height="match_parent"  
    10.         android:id="@+id/tv_key"  
    11.         android:textSize="24dip"/>  
    12.     <TextView   
    13.         android:layout_width="match_parent"  
    14.         android:layout_height="match_parent"  
    15.         android:id="@+id/tv_value"  
    16.         android:textSize="24dip"  
    17.         android:gravity="right"/>  
    18. </LinearLayout>  



    ListViewService.java

    [java] view plaincopy
     
    1. package cn.xuhui.pro;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. import android.content.Context;  
    7. import android.content.Intent;  
    8. import android.widget.RemoteViews;  
    9. import android.widget.RemoteViewsService;  
    10.   
    11. public class ListViewService extends RemoteViewsService {  
    12.   
    13.     @Override  
    14.     public RemoteViewsFactory onGetViewFactory(Intent intent) {  
    15.         //这里很简单的给ListView一个List就好了  
    16.         List<String> list = new ArrayList<String>();  
    17.         for(int i = 1; i <= 30; i++) {  
    18.             list.add(i + "," + i);  
    19.         }         
    20.           
    21.         return new ListRemoteViewsFactory(this, list);  
    22.     }  
    23.       
    24.     private static class ListRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {  
    25.         private List<String> mList;  
    26.         private Context mContext;  
    27.           
    28.         //构造ListRemoteViewsFactory  
    29.         public ListRemoteViewsFactory(Context context, List<String> list) {  
    30.             mList = list;  
    31.             mContext = context;  
    32.         }  
    33.           
    34.           
    35.         @Override  
    36.         public int getCount() {  
    37.             //返回count  
    38.             return mList.size();  
    39.         }  
    40.   
    41.         @Override  
    42.         public long getItemId(int position) {  
    43.             //类似Adapter里面的getItemId,不用处理,一般直接返回就够了  
    44.             return position;  
    45.         }  
    46.   
    47.         @Override  
    48.         public RemoteViews getLoadingView() {  
    49.             //when ListView is scrolled, the loading view is not necessary  
    50.             //如果是StackView之类需要显示图片什么的,滑动的时候免得用户看到白板,就设置个Loading的View  
    51.             return null;  
    52.         }  
    53.   
    54.         @Override  
    55.         public RemoteViews getViewAt(int position) {  
    56.                         //这个方法相当于返回ListView的一个Item(类似Adapter里面的getView/getItem吧)  
    57.                         RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.list_item);  
    58.             String[] entry = mList.get(position).split(",");  
    59.             rv.setTextViewText(R.id.tv_key, entry[0]);  
    60.             rv.setTextViewText(R.id.tv_value, entry[1]);  
    61.                         Intent fillInIntent = new Intent(mContext, WidgetClickHandlerService.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  
    62.             fillInIntent.putExtra("clicked_item", mList.get(position));  
    63.             //记住,这里是不可以用setOnClickPendingIntent的,官方API上有说, PendingIntent对于CollectionViews是无效的.  
    64.                         rv.setOnClickFillInIntent(R.id.item_layout, fillInIntent);  
    65.             return rv;  
    66.         }  
    67.   
    68.         @Override  
    69.         public int getViewTypeCount() {  
    70.             //视图种类, 如果我们的集合里面就只有一种视图,那么返回1.附上官方的api doc  
    71.             /* 
    72.             Returns the number of types of Views that will be created by getView(int, View, ViewGroup).  
    73.             Each type represents a set of views that can be converted in getView(int, View, ViewGroup).  
    74.             If the adapter always returns the same type of View for all items, this method should return 1 
    75.             */  
    76.             return 1;  
    77.         }  
    78.   
    79.         @Override  
    80.         public boolean hasStableIds() {  
    81.             //return True if the same id always refers to the same object.  
    82.             //如果返回true, 同一个id总是指向同一个对象  
    83.             return true;  
    84.         }  
    85.   
    86.         @Override  
    87.         public void onCreate() {  
    88.             // TODO ready for data source  
    89.             //这个方法一般是准备或者处理数据源的,这里不做处理. 可以参看Gallery2的  
    90.         }  
    91.   
    92.         @Override  
    93.         public void onDataSetChanged() {  
    94.             // TODO demo only , no dataSet change, 可以参看Gallery2的  
    95.         }  
    96.   
    97.         @Override  
    98.         public void onDestroy() {  
    99.             mList.clear();  
    100.             mList = null;  
    101.         }  
    102.     }  
    103.   
    104. }  


    我们点击ListView的Item时就用一个服务简单弹一个Toast就可以了

    WidgetClickHandlerService .java

    [java] view plaincopy
     
    1. package cn.xuhui.pro;  
    2.   
    3. import android.app.Service;  
    4. import android.content.Intent;  
    5. import android.os.IBinder;  
    6. import android.widget.Toast;  
    7.   
    8. public class WidgetClickHandlerService extends Service {  
    9.   
    10.     @Override  
    11.     public IBinder onBind(Intent intent) {  
    12.         return null;  
    13.     }  
    14.       
    15.     @Override  
    16.     public void onStart(Intent intent, int startId) {  
    17.         super.onStart(intent, startId);  
    18.         String data = intent.getStringExtra("clicked_item");  
    19.         Toast.makeText(this, data, Toast.LENGTH_LONG).show();  
    20.     }  
    21.   
    22. }  


    MyAppWidgetProvider.java

    [java] view plaincopy
     
    1. package cn.xuhui.pro;  
    2.   
    3.   
    4. import android.app.PendingIntent;  
    5. import android.appwidget.AppWidgetManager;  
    6. import android.appwidget.AppWidgetProvider;  
    7. import android.content.ComponentName;  
    8. import android.content.Context;  
    9. import android.content.Intent;  
    10. import android.widget.RemoteViews;  
    11.   
    12. public class MyAppWidgetProvider extends AppWidgetProvider {  
    13.     @Override  
    14.     public void onUpdate(Context context, AppWidgetManager appWidgetManager,  
    15.             int[] appWidgetIds) {  
    16.         RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.main);  
    17.         Intent intent = new Intent(context, ListViewService.class);  
    18.         rv.setRemoteAdapter(R.id.list_data, intent);  
    19.         //注意,下面这段代码不能少,否则点击没有效果  
    20.                 Intent clickIntent = new Intent(context, WidgetClickHandlerService.class);  
    21.                 PendingIntent pendingIntent = PendingIntent.getService(  
    22.                 context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);  
    23.         rv.setPendingIntentTemplate(R.id.list_data, pendingIntent);  
    24.         appWidgetManager.updateAppWidget(new ComponentName(context, MyAppWidgetProvider.class), rv);  
    25.     }  
    26. }  


    最后AndroidManifest.xml

    [html] view plaincopy
     
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     package="cn.xuhui.pro"  
    4.     android:versionCode="1"  
    5.     android:versionName="1.0" >  
    6.   
    7.     <uses-sdk android:minSdkVersion="15" />  
    8.   
    9.     <application  
    10.         android:icon="@drawable/ic_launcher"  
    11.         android:label="@string/app_name" >  
    12.         <!--这里必须加上这个权限, 否则报错 -->  
    13.         <service   
    14.             android:name=".ListViewService"  
    15.             android:permission="android.permission.BIND_REMOTEVIEWS"  
    16.             />  
    17.           
    18.         <service   
    19.             android:name=".WidgetClickHandlerService"  
    20.             />  
    21.           
    22.         <receiver android:name=".MyAppWidgetProvider"  
    23.             android:label="xh_demo">  
    24.             <intent-filter>  
    25.                 <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>  
    26.             </intent-filter>  
    27.             <meta-data android:name="android.appwidget.provider"  
    28.                     android:resource="@xml/widget_provider" />  
    29.         </receiver>  
    30.     </application>  
    31.   
    32. </manifest>  


    好了, 今天就总结到这里, 以后有时间再来研究一些Widget的东西吧

    原文:http://blog.csdn.net/izard999/article/details/7444457

  • 相关阅读:
    C#代码
    属性面板:tabcontroller
    窗体效果
    c#窗体开发
    帝国cms学习
    在树莓派上运行 .net core 2.1 程序 并实现开机启动
    C# 高性能的数组 高性能数组队列实战 HslCommunication的SharpList类详解
    C# 序列化详解,xml序列化,json序列化对比
    C# 读写redis C#读写实时数据库
    python 读写三菱PLC数据,使用以太网读写Q系列,L系列,Fx系列的PLC数据
  • 原文地址:https://www.cnblogs.com/veins/p/3834455.html
Copyright © 2011-2022 走看看