Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android學習筆記:Home Screen Widgets(1):關於Widget

Android學習筆記:Home Screen Widgets(1):關於Widget

編輯:關於Android編程

何為Home Screen Widgets

Home screen Widget即稱為小工具或者中文小工具,是顯示在主頁上的views,通過後台進程更新view的數據。

Android由AppWidgetManager來管理系統的widgets。安裝apk後,會根據widget定義在widget列表中顯示該Widget的名稱、圖標以及所占空間,在Android4.0中,以網格方式來顯示,有些OEM廠商會對UI進行重新設計,widget列表的展現形式會有所不同。

我們長按widget列表中的某個widget,將其拖拽到主頁上,實際上是AppWidgetManager在主頁上創建該widget的一個實例(instance)。可以有多個實例,不同實例用widgetID來區分它們。

widget定義兩個重要的java 類,一個是widget configurator activity,在widget實例生成時,被AppWidgetManager通過intent喚起進行初始化配置,其中action名為android.appwidget.action.APPWIDGET_CONFIGURE,這個java類是可選的,通常在此進行配置數據的輸入和保存,由於數據量少,可以很方便地保存在shared preference中。如果我們創建了兩個widget實例,這個配置activity會被調用兩次。

一個Java類,負責管理widget的生命周期,包括當拖拽到主頁時,需要更新時,以及拖入到垃圾桶時的處理。它是AppWidgetProvider的繼承,本質是一個廣播接收器,根據AppWidgetManager發出的廣播信息,觸發不同的回調函數,例如widget數據更新時間間隔(在widget定義中給出),widget實例的生成和刪除,第一個widget實例的生成,最後一個widget實例的刪除。

widget在頁面上的生成是由AppWidgetManager根據我們在widget定義中給出的layout文件生成有關的UI,不是由我們的代碼直接生成,因此我們也無法向在activity中那也直接對widget中的view進行操作,需要通過RemoteViews,提交給AppWidgetManager對某個實例進行處理。

小例子

我們將通過小例子,詳細解讀如何創建一個widget。小例子是一個生日提醒器。

\

在生成widget實例時,彈出配置activity,在activity中輸入名字和出生日期,按“設置”按鈕將數據保存在preference中,並關閉activity。

widget最上的view顯示widget_id:名字,中間左邊顯示距下一次生日的天數,點擊右邊的view可打開某個網頁,下面顯示出生日期。


定義廣播接收器

前面提到Widget有兩個重要的java類,一個是可選的用於配置的activity,一個用於管理wdiget生命周期的廣播接收器,接收器接收AppWidgetManager的廣播消息,來觸發各類回調函數。我們需在AndroidManifest.xml中定義這兩個java類,下面給出廣播接收器的類定義。



… …
<receiver android:name=".BirthDayWidgetProvider">

<intent-filter>




這個類是繼承android.appwidget.AppWidgetProvider,通過meta-data設置有關的參數。

這裡補充一下meta-data的知識,最為常見的是采用鍵值對的方式,即,在組件中可以獲得該數值,例如在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,內容如下。


<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">

在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。<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPtf3zqrKtdHp0KHA/dfTo6y/ydLUuMTOqjHQocqxo6y1q7K7xNzJ6NbDzKu2zKOswP3I5zG31tbTo6zU2sSjxOLG97XEyrXR6dbQo6zI57n7yrG85LzkuPTMq7bMyseyu7vhvfjQ0LSlt6K1xKGjPC9wPgo8cD4KtNNTREszLjG/qsq8o6zTw7uns6SwtHdpZGdldKOsv8nS1HJlc2l6ZSB3aWRnZXSjrLD8wKhob3Jpem9udGFso6x2ZXJ0aWNhbLrNbm9uZaGj0qrE3Lm7cmVzaXplo6zSqsfzbGF5b3V0ss7K/b/JyezL9aOs16LS4qOsyOe5+3NpemW4xLHkysfDu9PQY2FsbGJhY2vM4dDRtcShoyC+38zlyOe6znJlc2l6ZbK7zKvD98i3oaM8L3A+CjxwPgpwcmV2aWV3SW1hZ2XKx9Tad2lkZ2V0IGxpc3S1xM28seqjrMjnufvDu9PQ1eLP7qOsyrXTw21hbmlmZXN0zsS8/tbQtqjS5bXEbWFpbiBpY29uoaN3aWRnZXTB0LHt1tC1xM/Uyr7SsrPGzqpwcmV2aWV3oaM8YnI+CjwvcD4KPGgzPgrF5NbDQWN0aXZpdHm1xLao0uU8L2gzPgo8cD4K1NphcHB3aWRnZXQtcHJvdmlkZXLW0M2ouf1hbmRyb2lkOmNvbmZpZ3VyZbao0uXF5NbDtcRqYXZhwOBDb25maWdCaXJ0aERheVdpZGdldEFjdGl2aXR5o6zV4srHuPbG1c2otcRhY3Rpdml0eaOs0OjSqtTaQW5kcm9pZE1hbmlmZXN0LnhtbNbQvfjQ0Mu1w/ejrLKi1qez1s/s06ZBUFBXSURHRVRfQ09ORklHVVJFIGFjdGlvbqOsQW5kcm9pZE1hbmlmZXN0LnhtbLXEtPrC68asts7I58/Co7o8L3A+CjxwPgo8YWN0aXZpdHkgYW5kcm9pZDpuYW1lPQ==".ConfigBirthDayWidgetActivity" android:label="配置生日小工具">




至此,我們完成了widget的定義,即使我們沒有具體編寫任何的java類代碼,我們仍可以將其打包,並在設備上安裝。安裝後在widget列表中看到我們的小例子TestWidget。

Widget的外觀定義

在appwidget-provider中通過android:initialLayout定義widget的外觀。相應的layout/birday_widget.xml如下:


android:layout_width="150dp"
android:layout_height="120dp"
android:orientation="vertical"
android:background="@drawable/box1">
android:layout_width="match_parent"
android:layout_height="30dp"
android:text="Anonymous"
android:background="@drawable/box1"
android:gravity="center"/>
android:layout_width="match_parent"
android:layout_height="60dp">
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="0"
android:gravity="center"
android:textSize="30sp"
android:layout_weight="50"/>
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"/>

android:layout_width="match_parent"
android:layout_height="30dp"
android:text="2000/1/1"
android:background="@drawable/box1"
android:gravity="center"/>"

和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的內容如下:



<stroke android:width="4dp" android:color="#888888"/>
<padding android:left="2dp" android:top="2dp" android:right="2dp" android:bottom="2dp"/>
<corners android:radius="4dp" />


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved