除了要從選單點選來執行的應用程式外,還有另一種呈現的方式,那就 Widget 模式,也就是在廣告單上常常看到簡介某大廠 Android 手機時,其手機畫面正顯示的天氣資訊,有點像似待機時顯示在背景的資訊。這種程式實作上並沒有特別困難,但是我看了一些文章教學,反而很著重在介面設計,畢竟 Widget 的特色就是要美美的,結果對我這種介面沒經驗的人來說,往往第一步就卡住了,像是要用內建的 draw9patch 去弄圖片等,故在此就先完全不理會,連什麼背景框框都不要,純粹用來筆記實作 Widget 的流程。
實做 Widget 跟一般 project 的設定沒有差太多,但還是要多留意:
- 建立專案時,不見得要使用 Activity
- 編寫 AndroidManifest.xml 檔案
- 新增描述 Widget 的檔案
- 設定 Widget 排版
- 實作更新 Widget 的物件
建立一個 project
[Eclipse]->[File]->[New]->[Android Project]
Project name: MyWidget
Build Target: Android 2.2
Application name: MyWidget
Package name: com.test.widget
Min SDK Version: 8
留意的是在此不啟用 Create Activity,這並不是必須的選項。啟用 Activity 的好處,可以規劃使用者在新增 Widget 時,可以在過程中可以多加設定動作。在此僅學習建立 Widget 的流程,就不多提了。
設定 AndroidManifest.xml 檔案
新增 <receiver> 等敘述標籤,別於以前的 <activity>。
<receiver android:name=".MyWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget" />
</receiver>
在此 reciever 的 name 代表之後會建立的 Class 名稱,也就用更新 Widget 資訊的。而 meta-data 中所描述的 resource 則是下一步要新增 Widget 的描述檔
完整描述:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.widget"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name=".MyWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget" />
</receiver>
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>
建立 xml/widget.xml 檔案,用以描述 Widget 的資訊
在 res 目錄裡建立新的目錄,名為 xml,接著在 res/xml 目錄裡建立一個檔案,可從 xml 按右鍵->[News]->[Other]->[Android]->[Android XML File],並填寫 File 為 widget.xml 並勾選 AppWidget Provider 的型態,最後就可以按 Finish 結束,接著開啟 xml/widget.xml 檔案進行編輯
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="1800000"
android:initialLayout="@layout/main"
>
</appwidget-provider>
在此 minWidth 和 minHeight 是設定 Widget 顯示的範圍,而 dp 的數值計算可參考官網的教學,在此不多談,而 updatePeriodMillis 代表此 Widget 更新的頻率,1000 代表 1 秒,所以 1800000 代表 30 分鐘更新一次,更新頻率不宜過高,容易使得手機沒電。然而,經測試發現,目前內定的情境,無論把更新頻率弄到多快,最少要等 30 分鐘才會更新一次,解決的方式也不是沒有,在此先不多談。
設定排版部份
在此使用預設的 main.xml 檔案,開啟 main.xml 檔案後,替已存在的 TextView 加上 android:id="@+id/now"、android:gravity="center"、android:textColor="@android:color/black" 和 android:textSize="18sp" ,另外,再把 layout_height 更新為 fill_parent 即可。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/now"
android:gravity="center"
android:textColor="@android:color/black"
android:textSize="18sp"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="@string/hello"
/>
</LinearLayout>
實做 Widget 的資訊更新
在 src/com.test.widget 裡,新增一個 Class 名為 MyWidget.java
package com.test.widget;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;
public class MyWidget extends AppWidgetProvider {
@Override
public void onUpdate(Context context,AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews updateViews = new RemoteViews( context.getPackageName(), R.layout.main);
updateViews.setTextViewText(R.id.now, new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" ).format( new Date() ) );
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
}
}
最後,把程式 Run 起來,起初模擬器上不會顯示任何效果,因為 Widget 是要讓使用者自行設置的,需要透過模擬器鍵盤上的 [Menu]->[Add]->[Widgets] 就可以找到 MyWidget,點選下去才是真的安裝此 Widget 啦,成果就是螢幕上面多了一個時間囉!這也是 MyWidget.java 裡頭寫得東作,僅把 TextView 上的內容更新為時間。另外,若想要把已安裝的 Widget 刪除,僅需用滑鼠按住它,接著 Home 就會變成垃圾桶,拖進去就可以囉。