Pro Android学习笔记(一三六):Home Screen Widgets(2):Widget定义

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei

定义广播接收器

前面提到Widget有两个重要的java类,一个是可选的用于配置的activity,一个用于管理wdiget生命周期的广播接收器,接收器接收AppWidgetManager的广播消息,来触发各类回调函数。我们需在AndroidManifest.xml中定义这两个java类,下面给出广播接收器的类定义。

<manifest ……  >
    <application …… android:label="TestWidget" ……> <!-- android:label就是widget列表中的widget名称 -->
        … …

        <receiver android:name=".BirthDayWidgetProvider">
            <meta-data android:name="android.appwidget.provider" android:resource="@xml/birthday_widget_provider"/>
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>

        </receiver>
    </application>
</manifest>

这个类是继承android.appwidget.AppWidgetProvider,通过meta-data设置有关的参数。

这里补充一下meta-data的知识,最为常见的是采用键值对的方式,即<meta-data android:name="xxx" android:value="yyy" />,在组件中可以获得该数值,例如在activity中:

ActivityInfo actInfo = mContext.getPackageManager().getActivityInfo( getComponentName(), PackageManager.GET_META_DATA);  
String msg = actInfo.metaData.getString("activity_name");

而在service,则为ServiceInfo,在application中为ApplicationInfo,在receiver中为ActivityInfo,但用getReceiverInfo, 如果需要ComponentName参数,可以用 new ComponentName(context, MyComponent.class)来获取。

我们看看android.appwidget.AppWidgetManager.java的有关代码:

/**
* Sent when it is time to update your AppWidget.
*
* This may be sent in response to a new instance for this AppWidget provider having
* been instantiated
, the requested {@link AppWidgetProviderInfo#updatePeriodMillis update interval} having lapsed, or the system booting.
* ……
*
* @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
*/

public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";

/** 
   * Field for the manifest meta-data tag. 
   * 
   * @see AppWidgetProviderInfo 
   */
 
public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";

在meta-data中,android.appwidget.provider为Android指定的关键字,用于在对应的resource中定义App Widget Provider信息的文件,该文件位于xml/下,本例子为res/xml/birthday_widget_provider.xml,定义widget的参数。

android.appwdiget.action.APPWIDGET_UPDATE是接收器监听AppWidgetManger的广播消息之一,其他还监听ACTION_APPWIDGET_ENABLED等等消息,但在receiver中必须指明是ACTION_APPWIDGET_UPDATE,系统才可识别出接收器实际是widget,才能在widget列表中添加该widget。其他需要监听的消息无需在此列出。

App widget provider的定义

在manifest.xml中,通过meta-data给出appwidget provider定义所在文件为xml/birthday_width_provider.xml,内容如下。

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="150dp"
    android:minHeight="120dp"
    android:updatePeriodMillis="43200000"
    android:initialLayout="@layout/birday_widget"
    android:configure="cn.wei.flowingflying.testwidget.ConfigBirthDayWidgetActivity"   
    android:previewImage="@drawable/gift"
    android:resizeMode="horizontal|vertical">
</appwidget-provider>

在widget列表中显示widget的大小为3×2。在xml中,我们定义长150dp,宽120dp,实际上widget在Home Screen占据的空间是按网格计算的,每个网格为74dp×74dp,系统会分配所需容纳的网格。一般手机网格为4×4,平板为8×7。在《Pro Android》一书中给出建议为74的N倍减去2dp(适配边框),而在Android开发者网站推荐定义的min长宽为70*N-30,下面是给出的一个例子:

本例间隔时间为12小时(43200000ms)。Android强烈建议1天最多只有几次,不要太多。从Android2.0开始,最小值为30分钟。如果我们设置为0,表示不会自动update,我们可以通过AlarmManager类来自行控制何时update。作为实验小例子,可以改为1小时,但不能设置太短,例如1分钟,在模拟器的实验中,如果时间间隔太短是不会进行触发的。

从SDK3.1开始,用户长按widget,可以resize widget,包括horizontal,vertical和none。要能够resize,要求layout参数可伸缩,注意,如果size改变是没有callback提醒的。 具体如何resize不太明确。

previewImage是在widget list的图标,如果没有这项,实用manifest文件中定义的main icon。widget列表中的显示也称为preview。

配置Activity的定义

在appwidget-provider中通过android:configure定义配置的java类ConfigBirthDayWidgetActivity,这是个普通的activity,需要在AndroidManifest.xml中进行说明,并支持响应APPWIDGET_CONFIGURE action,AndroidManifest.xml的代码片段如下:

<activity android:name=".ConfigBirthDayWidgetActivity" android:label="配置生日小工具">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
    </intent-filter>
</activity>

至此,我们完成了widget的定义,即使我们没有具体编写任何的java类代码,我们仍可以将其打包,并在设备上安装。安装后在widget列表中看到我们的小例子TestWidget。

Widget的外观定义

在appwidget-provider中通过android:initialLayout定义widget的外观。相应的layout/birday_widget.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="150dp"
    android:layout_height="120dp"
    android:orientation="vertical"
    android:background="@drawable/box1">
    <TextView android:id="@+id/bd_name"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:text="Anonymous"
        android:background="@drawable/box1"
        android:gravity="center"/>
    <LinearLayout android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <TextView android:id="@+id/bd_days"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="0"
            android:gravity="center"
            android:textSize="30sp"
            android:layout_weight="50"/>
        <TextView android:id="@+id/bd_buy"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:textSize="20sp"
            android:text="Buy"
            android:layout_weight="50"
            android:background="#FF6633"
            android:gravity="center"/>
    </LinearLayout>
    <TextView android:id="@+id/bd_date"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:text="2000/1/1"
        android:background="@drawable/box1"
        android:gravity="center"/>"
</LinearLayout>

和activity不同,不能直接在代码中获取view的对象并进行控制,需要通过AppWidgetManager用RemoteViews来进行间接控制。因此在widget外观定义中,view需要能支持remote view,包括FrameLayout、LinearLayout、RelativeLayout、AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper。

Android给出widget外观设计的guideline,见http://developer.android.com/guide/practices/ui_guidelines/widget_design.html

通过android:background="@drawable/box1",可以定义外围轮廓。res/drawable/box1.xml的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <stroke android:width="4dp" android:color="#888888"/>  <!--定义边框 -->
    <padding android:left="2dp" android:top="2dp" android:right="2dp" android:bottom="2dp"/>
    <corners android:radius="4dp" />
</shape>

 

 小例子代码在: Pro Android学习:widget小例子

相关链接:我的Android开发相关文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值