现在的位置: 首页 > 移动开发 > 正文

Android Widget日历 完整示例分析

2018年09月18日 移动开发 ⁄ 共 10225字 ⁄ 字号 评论关闭

 第六部分 Widget日历
   本例实现了Widget日历,用来显示当前的日期,时间等信息。要学习开发Widget开发,需要了解AppWidget的框架结构。基于该框架,开发者可以在Ophone及模拟器上开发"外形"
   类似传统的Widget小应用程序,并将其嵌入到其他应用中。
    注意:Widget设计好UI后根据需要来完成更新,如果程序不需要使用定时来更新AppWidget,则最好不要使用定时更新,因为它会增加电量和CUP资源的开销。我们可以定义一个线程,当需要
   时才更新,这样可以让Widget达到最高效率
   AppWidget框架主要包括以下类:
    AppWidgetProvider: 该类继承自BroadcastReceiver,在AppWidget应用update、enable、disable、deleted时接受通知。其中,onUpdate、onReceive用来接收更新通知。
    AppWidgetProviderInfo:该类主要用于AppWidget的大小、更新频率和初始界面等信息,以XML文件形式存在于res/xml目录下。
    AppWidgetManager:该类负则管理AppWidget,及向AppWidgetProvider发送通知。
    RemoteViews:一个可以在其他应用进程中运行的类,是构造AppWidget的核心。
    
   Widget开发流程
   res.layout.widget_layout.xml
   <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:minHeight="146dp"
     android:minWidth="146dp"
     android:background="@drawable/bgblack"
     android:id="@+id/Base"
     >
     <LinearLayout //需要3个TextView来显示日期
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="vertical"
      android:layout_gravity="center"
      android:paddingTop="5dip"
      >
      <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/Month"
       android:layout_gravity="center"
       android:textStyle="bold"
       android:textSize="18sp"
       android:textColor="#FFFFFF"
      ></TextView>
      <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center"
       android:id="@+id/Date"
       android:textStyle="bold"
       android:textSize="70sp"
       android:textColor="#FFFFFF"
      ></TextView>
      <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/WeekDay"
       android:layout_gravity="center"
       android:textSize="15sp"
       android:textStyle="bold"
       android:textColor="#FFFFFF"
      ></TextView>
     </LinearLayout>
    </LinearLayout>
   
   res.xml.widget.xml
   <?xml version="1.0" encoding="utf-8"?>//一个能反映出AppWidgetProviderInfo信息的布局文件。AppWidget的像素大小取决于它所占方块多少(计算公式(块数*74)-2),因此
              取高度为146像素,宽度是146像素
    <appwidget-provider
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:initialLayout="@layout/widget_layout" //设置AppWidget的布局文件为widget_layout布局
     android:minWidth="146dip"
     android:minHeight="146dip"
     android:updatePeriodMillis="3600000">
    </appwidget-provider>

   //res.xml.widget_small.xml
   //<?xml version="1.0" encoding="utf-8"?>
   // <appwidget-provider
   //  xmlns:android="http://schemas.android.com/apk/res/android"
   //  android:initialLayout="@layout/widget_layout"
   //  android:minWidth="72dip"
   //  android:minHeight="72dip"
   //  android:updatePeriodMillis="3600000">
   // </appwidget-provider>
    
   //res.layout.widget_layout_small.xml
   //<?xml version="1.0" encoding="utf-8"?>
   // <LinearLayout
   //  xmlns:android="http://schemas.android.com/apk/res/android"
   //  android:orientation="vertical"
   //  android:layout_width="wrap_content"
   //  android:layout_height="wrap_content"
   //  android:minHeight="72dip"
   //  android:minWidth="72dip"
   //  android:background="@drawable/bgblacksmall"
   //  android:id="@+id/SmallBase"
   //  >
   //  <LinearLayout
   //   android:layout_width="wrap_content"
   //   android:layout_height="wrap_content"
   //   android:orientation="vertical"
   //   android:layout_gravity="center"
   //   android:paddingTop="5dip"
   //   >
   //   <TextView
   //    android:layout_width="wrap_content"
   //    android:layout_height="wrap_content"
   //    android:id="@+id/Month"
   //    android:layout_gravity="center"
   //    android:textStyle="bold"
   //    android:textSize="12sp"
   //    android:gravity="center"
   //    android:textColor="#FFFFFF"
   //   ></TextView>
   //   <TextView
   //    android:layout_width="wrap_content"
   //    android:layout_height="wrap_content"
   //    android:layout_gravity="center"
   //    android:id="@+id/Date"
   //    android:textStyle="bold"
   //    android:textSize="30sp"
   //    android:textColor="#FFFFFF"
   //   ></TextView>
   //  </LinearLayout>
   // </LinearLayout>

   public class TodayDate extends AppWidgetProvider{//当我们添加AppWidget应用或自动定时更新时,AppWidgetManager会广播动作名字是"android.appwidget.action.APPWIDGET_UPDATE"
                 的Intent,当onReceive()方法没有被重载时,onUpdate方法会接收到这些广播的Intent。类似BroadcastReceiver类,我们可以
                 重载AppWidgetProvider的onReceive方法,并在其中指定想要接收的Intent
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
     RemoteViews updateView = buildUpdate(context);
     appWidgetManager.updateAppWidget(appWidgetIds, updateView);
     super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
    private String[] months = {"一月", "二月", "三月", "四月","五月", "六月", "七月", "八月","九月", "十月", "十一月", "十二月"};
    private String[] days = {"星期日", "星期一", "星期二", "星期三","星期四", "星期五", "星期六"};
    private RemoteViews buildUpdate(Context context){
     RemoteViews updateView = null;
     Time time = new Time();
     time.setToNow();
     String month = months[time.month] + " " + time.year;
     updateView = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
     updateView.setTextViewText(R.id.Date, new Integer(time.monthDay).toString());
     updateView.setTextViewText(R.id.Month, month);
     updateView.setTextViewText(R.id.WeekDay, days[time.weekDay]);
     Intent launchIntent = new Intent();
     launchIntent.setComponent(new ComponentName("com.android.calendar", "com.android.calendar.LaunchActivity"));
     launchIntent.setAction(Intent.ACTION_MAIN);
     launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
     launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
     PendingIntent intent = PendingIntent.getActivity(context, 0, launchIntent, 0);
     updateView.setOnClickPendingIntent(R.id.Base, intent);
     return updateView;
    }
   }

   //public class TodayDateSmall extends AppWidgetProvider{
   // public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
   //  RemoteViews updateView = buildUpdate(context);
   //  appWidgetManager.updateAppWidget(appWidgetIds, updateView);
   //  super.onUpdate(context, appWidgetManager, appWidgetIds);
   // }   
   // private String[] months = {"一月", "二月", "三月", "四月","五月", "六月", "七月", "八月","九月", "十月", "十一月", "十二月"};  

   // private RemoteViews buildUpdate(Context context) {
   //  RemoteViews updateView = null;
   //  Time time = new Time();
   //  time.setToNow();
   //  String month = months[time.month];
   //  updateView = new RemoteViews(context.getPackageName(), R.layout.widget_layout_small);
   //  updateView.setTextViewText(R.id.Date, new Integer(time.monthDay).toString());
   //  updateView.setTextViewText(R.id.Month, month);
   //  Intent launchIntent = new Intent();
   //  launchIntent.setComponent(new ComponentName("com.android.calendar", "com.android.calendar.LaunchActivity"));
   //  launchIntent.setAction(Intent.ACTION_MAIN);
   //  launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
   //  launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   //  PendingIntent intent = PendingIntent.getActivity(context, 0, launchIntent, 0);
   //  updateView.setOnClickPendingIntent(R.id.SmallBase, intent);
   //  return updateView;
   // }
   //}

   AndroidManifest.xml
   <?xml version="1.0" encoding="utf-8"?>//因为使用了receiver及"adroid.appwidget.action.APPWIDGET_UPDATE"所以需要声明权限
    <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.yarin.android.TodayDate"
     android:versionCode="1"
     android:versionName="1.0">
     <application
      android:icon="@drawable/icon"
      android:label="@string/app_name">
      <receiver
       android:label="@string/app_name"
       android:name=".TodayDate">
       <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
       </intent-filter>
       <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/widget">
       </meta-data>
      </receiver>
      <receiver
       android:label="@string/app_name_small"
       android:name=".TodayDateSmall">
       <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
       </intent-filter>
       <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/widget_small">
       </meta-data>
      </receiver>
     </application>
     <uses-sdk android:minSdkVersion="5" />
    </manifest>
    
   续:
   1、上例中只是更新显示了一个界面,在Widget中同样可以通过setOnClickPendingIntent方法来监听一个事件的处理,下面代码中当我们点击了"widget_button"按钮时,会弹出Toast提示
    public class widget extends AppWidgetProvider{
     public void onReceive(Context context, Intent intent){
      super.onReceive(context,intent);
      if(intent.getAction().equals("com.android.myapp.widget.CLICK")){
       Toast.makeText(context ,"It works!!", Toast.LENGTH_SHORT).show();
      }
     }
     public void onUpdate(Context context,AppWidgetManager mgr, int[] appWidgetIds){
      final int N = appWidgetIds.length;
      for(int i=0; i<N; i++){
       int [] appWidgetId = appWidgetIds;
       RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
       Intent clickintent = new Intent("com.android.myapp.widget.CLICK");
       PendingIntent pendingIntentClick = PendingIntent.getBroadcast(context, 0,clickintent,0);
       views.setOnClickPendingIntent(R.id.widget_butt,PendingIntentClick);
       mrg.updateAppWidget(appWidgetId,views);
      }
     }
    }
   2、在Widget中启动一个Activity,
     RemoteViews rv = new RemoteViews(context.getPackageName(),R.layout.mywidget);
     Intent intentActivity = new Intent(context, MusicPlayer.class);//此处启动一个音乐播放界面
     PendingIntent pendingIntentActivity = PendingIntent.getActivity(context,0,intentActivity,0);
     rv.setOnClickPendingIntent(R.id.button,pendingIntentActivity);
     appWidgetManager.updateAppWidget(appWidgetId,rv);
     context.startActivity(intentActivity);//当点击"button"按钮时启动自动Activity
   3、Wdiget启动Service
     RemoteViews rv = new RemoteViews(context.getPackageName(),R.layout.mywidget);
     Intent intentService = new Intent("Service名字");
     context.startService(intentService);
     appWidgetManager.updateAppWidget(appWdigetgetId,rv);
     

抱歉!评论已关闭.