從零開始–系統深入學習android(實踐-讓我們開始寫代碼-Android架構學習-7.App Widgets)

來源:互聯網
上載者:User
第7章 App Widgets

App Widgets是一個應用程式的微型視圖,可以嵌入到其他應用程式(如主畫面)並且能夠定期更新。你發行就緒一個應用程式的App Widget,而這些視圖稱為視窗的使用者介面。一個應用程式組件,可以支援其他應用程式的App Widgets稱為App Widget的主機(host)。下面的是顯示音樂的App Widget。

該文檔將介紹如何在應用程式裡發布和使用App Widget。

7.1 基礎知識

要建立一個App Widget,您需要瞭解以下幾點:

◆AppWidgetProviderInfo對象:
描述了一個App Widget的中繼資料,如在App
Widget的布局,更新頻率,和AppWidgetProvider類。都應在XML中定義。
◆AppWidgetProvider類的實現:
定義一個基於廣播事件與App Widget的介面方法。通過它,您將收到廣播對App Widget進行更新,啟用,禁用和刪除。
◆視圖布局:
在XML中初步定義App Widget布局。
此外,還可以實現App Widget可配置的Activity。當使用者添加您的App Widget,並允許他或她在建立時修改設定時啟動這個可配置的Activity。
該文檔將介紹如何在應用程式裡發布和使用App Widget。

7.2 在Manifest.xml中聲明App Widgets

首先,在您的應用程式的AndroidManifest.xml檔案中應聲明AppWidgetProvider類。例如代碼清單7-1所示:

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

 

代碼清單 7-1

<receiver>節點需要的android:name屬性,在App Widget中指定使用AppWidgetProvider。 <intent-filter>節點必須包含一個<action>節點的name屬性。此屬性指定AppWidgetProvider接受ACTION_APPWIDGET_UPDATE廣播。這是唯一的廣播,你必須明確聲明。在AppWidgetManager自動發送其他App widget廣播到AppWidgetProvider是必要的。<meta-data>節點指定的AppWidgetProviderInfo的資源,需要以下屬性:

android:name - 指定的中繼資料的名稱。使用android.appwidget.provider識別作為

◆AppWidgetProviderInfo描述符的資料。

◆android:resource - 指定的AppWidgetProviderInfo的資源位置。

7.3 添加AppWidgetProviderInfo中繼資料

AppWidgetProviderInfo是定義App Widget的本質,例如其最小的布局尺寸,初始布局資源,如何更新App Widget,和(可選)配置Activity,在建立時發起。在XML資源檔中定義AppWidgetProviderInfo對象,使用<appwidget-provider>節點和在項目的res / xml/檔案夾中儲存。如代碼清單7-2所示:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    android:minWidth="294dp"    android:minHeight="72dp"    android:updatePeriodMillis="86400000"    android:previewImage="@drawable/preview"    android:initialLayout="@layout/example_appwidget"    android:configure="com.example.android.ExampleAppWidgetConfigure"     android:resizeMode="horizontal|vertical"></appwidget-provider>

 

代碼清單 7-2

以下是<appwidget-provider>屬性的摘要,在這之前最好你已經閱讀了第一部分的Widget設計章節:

◆App Widget預設的情況下minWidth和MinHeight屬性值指定最小佔據的空間,AppWidgets預設是在Home螢幕位置,在其視窗基礎上的儲存格中有一個明確高度和寬度的網格。如果一個App Widget的最小寬度或高度值不匹配儲存格的尺寸,則App Widget尺寸向上舍入到最接近的儲存格大小。

註:為了使App Widget更容易移植在不同裝置,App Widget的最小尺寸不應大於4×4儲存格

◆minResizeWidth和minResizeHeight屬性指定App Widget的絕對最小尺寸。這些值應該指定尺寸下,否則應用程式組件將無法辨認或以其他方式使用。在android3.1,允許使用者使用這些屬性調整控制項大小,可能是小於預設尺寸界定的minwidth和minheight屬性。

◆updateperiodmillis屬性定義,往往在App Widget架構,應從appwidgetprovider請求通過調用onupdate()回調方法更新。實際上不能保證更新的準確性,我們建議儘可能的少更新或者不超過每小時一次,以此來節省電池。你也可以在configuration-some中允許使用者調整頻率,比如證劵報價機,一些使用者可能想要15分鐘更新一次,一些則想要每天只更新四次

註:如果該裝置是睡著的,而它是一個更新的時間(定義updatePeriodMillis)時,則該裝置將被喚醒以執行更新。如果你不超過每小時更新一次,這可能不會對電池壽命造成重大的問題。但是,如果您需要頻繁更新或你並不需要更新,而裝置是睡著的,你就可以根據警示代替執行,則不會喚醒裝置執行更新。要做到這一點,設定一個Intent,當您的AppWidgetProvider收到的警示時,使用AlarmManager。設定警示類型有ELAPSED_REALTIME或RTC,這在收到警示時,該裝置被喚醒。然後設定updatePeriodMillis為零(“0”)。

◆initialLayout的屬性指向布局資源,它定義了App Widget的布局。

◆在Activity啟動時對屬性進行配置定義,使用者添加App Widget,以便讓使用者配置App Widget屬性。這是可選的。

◆在配置previewImage屬性後將指定一個App Widget表徵圖是什麼樣子,當選擇這個App Widget時使用者可以進行預覽。如果沒有提供表徵圖,使用者卻認為laucher是您的應用程式圖示。這個欄位對應android:previewImage進行在 <receiver>元素的AndroidManifest.xml檔案中。在android3.0引入。

◆在Android 3.0引入,該autoAdvanceViewId屬性指定的App Widget子視圖的視圖ID。

◆在Android 3.1引入,該resizeMode屬性指定其中一個可以調整規則的Widget。您可以使用此屬性使主畫面Widget的調整方式,如水平,垂直,或兩軸。使用者長按一個Widget,會顯示其調整的介面,然後拖動水平和/或垂直的控鍵,改變布局網格的大小。resizemode屬性值包括"horizontal", "vertical", 和"none"。兩者都有如“horizontal | vertical”。

7.4 建立App Widget布局

你必須為你的App widget定義初始布局,你可以在XML定義並儲存在項目的res/layout/目錄中。你可以使用下列的View對象來設計你的App widget,但在你開始設計你的App widget之前,請閱讀和理解App widget的設計準則。 如果你熟悉XML的布局,建立App widget的布局很簡單。然而,你們必須知道App widget的布局都是基於RemoteViews類,它不支援各種布局或view widget。
一個RemoteViews對象支援以下布局類:

FrameLayout

LinearLayout

RelativeLayout

以下View支援widget:

AnalogClock

Button

Chronometer

ImageButton

ImageView

ProgressBar

TextView

ViewFlipper

ListView

GridView

StackView

AdapterViewFlipper

但是這些類的子類卻都不支援。

1. 添加邊距到App Widgets

widget通常不應該擴充到螢幕邊緣,不應與其他widget視圖共同重新整理,所以你應該在你的widget框中增加邊距。自Android 4.0起,App widget提供了widget之間的自動填滿架構和App widget的包圍盒,以便使用者在home螢幕更好的調整其他widget和表徵圖。要獲得這種功能,你需要吧應用程式的targetSdkVersion設定為14或更高。
早期版本,編寫一個布局很容易,並可以自訂邊距,在Android4.0或以上版本並沒有額外的邊距,步驟如下:
◆設定應用程式的targetsdkversion值為14或更高。
◆建立一個如下布局,引用dimension資源,如代碼清單7-3所示:

<FrameLayout  android:layout_width="match_parent"  android:layout_height="match_parent"  android:padding="@dimen/widget_margin">   <LinearLayout    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal"    android:background="@drawable/my_widget_background">    …  </LinearLayout> </FrameLayout>

 

代碼清單 7-3

◆建立兩個dimensions 的資源,一個在res /values/提供Android 4.0之前的自訂邊距,一個在res/values-v14/沒有為Android4.0widgets提供額外的padding:
res/values/dimens.xml:

<dimen name="widget_margin">8dp</dimen>

res/values-v14/dimens.xml:

<dimen name="widget_margin">0dp</dimen>

 

7.5 使用AppWidgetProvider類

首先,你必須在AndroidManifest<receiver>節點裡聲明 的AppWidgetProvider類的實現(參見本章的“7.2在Manifest.xml中聲明App Widgets” )。

AppWidgetProvider繼承broadcastreceiver用來處理App widget廣播非常方便。 AppWidgetProvider只接收和App widget相關的事件廣播,如App widget進行更新時,相關的App widget進行刪除,啟用和禁用。這些廣播事件發生時,AppWidgetProvider將調用以下的方法:
◆onUpdate() 

這種在AppWidgetProviderInfo由updatePeriodMillis屬性定義的時間間隔來使AppWidget更新。當使用者添加App widget時,這種方法也被調用,所以它應該進行基本的設定,如定義View事件的處理,如果有必要,還應啟動臨時service。不過,如果你已經聲明配置的Activity,當使用者添加App widge這種方法則不會調用,而是後續更新調用。配置的Activity完成後,它的作用就是執行首次更新。

◆onAppWidgetOptionsChanged()

當wodget第一次被調整時被調用。你能使用這個回調來顯示或隱藏內容。你可以通過getAppWidgetOptions()來獲得大小範圍,它返回一個Bundle,你可以使用下面String鍵,來獲得值:

AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH—當前寬度的最小值,單位是DP

AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT—當前高度的最小值,單位是DP

AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH—當前寬度的最大值,單位是DP

AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT—當前高度的最大值,單位是DP

Android4.1從在引入這個方法。請注意

◆onDeleted(Context, int[])

每次一個App Widget從App Widget主機中刪除時被調用。

◆onEnabled(Context)

首次建立App widget執行個體時調用。例如,如果使用者為同一個App widget添加了兩個執行個體,這也只調用一次。如果你需要開啟一個新的資料庫或進行其他的設定,那麼在這個地方執行個體是非常好的。

◆onDisabled(Context)

當最後一個App widget的執行個體時從App
widget主機中刪除時被調用,使用onDisabled(Context)方法進行清理,比如刪除臨時資料庫。

◆onReceive(Context, Intent)

可以理解為一個通用廣播接收介面,上面的每個方法的回調。你通常不需要實現這個方法,因為預設的AppWidgetProvider實現過濾器所有App widget廣播,並適當調用以上的方法。

 

當每個App
widget添加到一個主機時,最重要的是AppWidgetProvider onUpdate()方法回調(除非你使用一個配置的Activity)。如果你的App widget接受任何使用者互動事件,那麼在回調時,你需要註冊事件處理器。如果你的App
widget不能建立臨時檔案或資料庫,或者執行其他的工作,那就需要清楚,onUpdate()方法,可能是你唯一需要定義的回調方法。例如,如果你想要一個App widget上有一個按鈕,當點擊時啟動一個Activity,你可以這樣實現AppWidgetProvider,如代碼清單7-4所示:

public class ExampleAppWidgetProvider extends AppWidgetProvider {     public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {        final int N = appWidgetIds.length;         for (int i=0; i<N; i++) {            int appWidgetId = appWidgetIds[i];                 Intent intent = new Intent(context, ExampleActivity.class);            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);            views.setOnClickPendingIntent(R.id.button, pendingIntent);            appWidgetManager.updateAppWidget(appWidgetId, views);        }    }}

 

代碼清單 7-4

上面代碼清單7-4中的AppWidgetProvider只定義onupdate()方法,其目的是定義一個PendingIntent啟動一個Activity並使用使用setonclickpendingintent(int,pendingintent)附加到App widget按鈕。注意,在appWidgetIds中它包括一個迴圈遍曆每個條目,這是一個數組的id標識,確定每個App widget。這樣,如果使用者建立多個App widget的執行個體,然後他們都同時更新。然而,只有一個updateperiodmillis時間表將管理所有的App widget。例如,如果更新計劃被定義為每兩個小時,在第一個後等待一小時在添加第二個執行個體,那麼它們兩個都將使用第一個的周期而第二個更新周期會被忽略。讀者可以參考ApiDemos\src\com\example\android\apis\appwidget的例子。

AppWidgetProvider就是一個方便的類而已。如果你想直接接收App widget廣播,你可以實現自己的BroadcastReceiver或覆蓋的onReceive(Context, Intent) 方法。你需要注意以下幾個intent: 

ACTION_APPWIDGET_UPDATE

ACTION_APPWIDGET_DELETED

ACTION_APPWIDGET_ENABLED

ACTION_APPWIDGET_DISABLED

ACTION_APPWIDGET_OPTIONS_CHANGED

7.6 建立一個App Widget配置的Activity

如果你想要一個使用者,當他增加了一個新的App widget時來配置設定,那麼你可以建立一個App widget配置Activity。當前的Acitivity將自動啟動的App widget的主機,並允許使用者在建立時配置App widget的顏色,大小,更新周期或其他功能的設定。 這個配置Activity應該在Android manifest檔案中聲明是一個標準的Activity。然而,它將通過App widget主機使用ACTION_APPWIDGET_CONFIGURE Action來啟動,所以這個Activity需要接收這種Intent。如代碼清單7-5所示:

<activity android:name=".ExampleAppWidgetConfigure">    <intent-filter>        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>    </intent-filter></activity>

 

代碼清單 7-5

此外,Activity必須在AppWidgetProviderInfo XML檔案中聲明android:configure屬性(參見前面小節“添加AppWidgetProviderInfo中繼資料”)。例如,需要配置的Activity聲明如代碼清單7-6所示:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    ...    android:configure="com.example.android.ExampleAppWidgetConfigure"     ... ></appwidget-provider>

 

代碼清單 7-6

注意,這個Activity是聲明完整命名空間,因為它是從外部包引用的。
你需要的是啟動一個配置Activity。現在你所需要的是實際的Activity。然而,當你實現Activity有兩個重要的事情要記住:

◆這個App widget主機調用配置Activity,而配置Activity應該總是返回一個結果碼。這個結果碼應該包括App widget  ID。

◆當建立App widget時OnUpdate()方法將不會被調用(配置Activity啟動時,系統將不發送ACTION_APPWIDGET_UPDATE廣播)。

這是配置Activity的職責,它請求從App widget首次建立AppWidgetManager時更新。然而,onUpdate()方法將調用後續更新,它僅在第一次跳過。

請參閱以下的程式碼片段,看它怎樣返回配置和更新的App widget後的結果。

當一個App widget使用配置Activity時,這個Activity配置完成後負責更新App widget。你可以從AppWidgetManager通過請求直接更新。
1. 從通過Intent啟動的Activity中獲得App widget的ID:

Intent intent = getIntent();Bundle extras = intent.getExtras();if (extras != null) {    mAppWidgetId = extras.getInt(            AppWidgetManager.EXTRA_APPWIDGET_ID,             AppWidgetManager.INVALID_APPWIDGET_ID);}

 

2. 執行你的App widget配置.
3. 當配置完成後,通過調用getInstance(context)獲得一個AppWidgetManager執行個體:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

4. 通過調用updateAppWidget(int,RemoteViews)來使用RemoteViews布局更新App widget:

RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.example_appwidget);appWidgetManager.updateAppWidget(mAppWidgetId, views);

5. 最後,建立返回的intent,其設定Activity的結果,並終止該Activity:

Intent resultValue = new Intent();resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);setResult(RESULT_OK, resultValue);finish();

 

7.7 設定一個預覽的圖片

Android3.0之後引入了previewImage屬性,它指定一個Appwidget縮圖。下面讓我們看下代碼清單7-7,看看是如何設定的

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  ...  android:previewImage="@drawable/preview"></appwidget-provider>

代碼清單 7-7

為了協助您的Appwidget(指定在previewImage領域)建立預覽映像,在Android模擬器中包含一個應用程式被稱為“Widget Preview”。要建立預覽映像,則要啟動該應用程式,選擇你的應用程式的Appwidget,並設定你希望的預覽映像,然後將它儲存,並將其放置在你的應用程式的drawable資源下。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.