Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android API Guides---App Widgets

Android API Guides---App Widgets

編輯:關於Android編程

應用小工具

應用Widget是可以在其他應用程序(如主屏幕)嵌入並接受定期更新的微型應用程序的意見。這些觀點在用戶界面被稱為小工具,你可以發布一個與應用的Widget提供商。即能持有其他應用程序的窗口小部件的應用程序組件被稱為應用程序的Widget主機。下面的截圖顯示音樂應用的Widget。

\

本文介紹了如何使用應用程序的Widget提供者發布應用的Widget。為了創建自己的AppWidgetHZ喎?/kf/ware/vc/" target="_blank" class="keylink">vc3TN0Lnc06bTw9Chsr+8/rXEzNbC26Osx+uyztTE06bTw7XEV2lkZ2V01ve7+qGjPGJyPgo8YnI+Cjxicj4Kyei8xrXEV2lkZ2V0PGJyPgrT0LnYyOe6zsnovMbE47XE06bTw7PM0PK0sL/a0KGyv7z+tcTQxc+io6zH69TEtsG0sL/a0KGyv7z+tcTJ6LzG1rjEz6GjPGJyPgq7+bShPGJyPgo8YnI+Cjxicj4K0qq0tL2o0ru49tOm08OzzNDytLC/2tChsr+8/qOsxPrQ6NKqwvrX49LUz8LM9bz+o7o8YnI+Cjxicj4KPGJyPgpBcHBXaWRnZXRQcm92aWRlckluZm+21M/zPGJyPgrD6Mr21KrK/b7dzqrTptPDtcRXaWRnZXSjrMjn1NpBcHAgV2lkZ2V0tcSyvL7Wo6y4/NDCxrXCyqOs0tS8sEFwcFdpZGdldFByb3ZpZGVywOCho9Xi06a1sdLUWE1MwLS2qNLloaM8YnI+CkFwcFdpZGdldFByb3ZpZGVywOC1xMq1z9Y8YnI+Crao0uW1xLv5sb63vbeoo6zIw8T60tSx4LPM0+vTptPDs8zQ8ndpZGdldL3nw+ajrLv509q547KltcTKwrz+oaPNqLn9y/yjrLWx06bTw7PM0PK1xFdpZGdldLG7uPzQwqOsxvTTw6OsvfvTw7rNyb6z/cT6vavK1bW9ueOypaGjPGJyPgrK0828sry+1jxicj4KtqjS5cHL06bTw7PM0PKy5bz+tcSz9cq8sry+1qOs1NpYTUzW0Lao0uWhozxicj4KtMvN4qOsu7m/ydLUyrXP1tK7uPbTptPDtcRXaWRnZXTF5NbDu+62r6Gj1eLKx9K7uPa/ydGhtcS77ravo6y1sdPDu6e9q8T6tcRXaWRnZXTTptPDs8zQ8qOssqLUytDty/u78sv91NrQ3rjEtLTX98qx06bTw9ChuaS+38no1sOjrMb0tq+hozxicj4KPGJyPgo8YnI+CtLUz8K4973aw+jK9sHLyOe6zsno1sPV4tCp1+m8/qGjPGJyPgo8YnI+Cjxicj4K1NrH5bWl1tDJ+cP30ru49tOm08OzzNDytLC/2tChsr+8/jxicj4KPGJyPgo8YnI+CsrXz8ijrMn5w/fU2tOm08OzzNDytcRBbmRyPz9vaWRNYW5pZmVzdC54bWzOxLz+1tC1xEFwcFdpZGdldFByb3ZpZGVywOCho8D9yOejujxicj4KPC9wPgo8cD48L3A+CjxwcmUgY2xhc3M9"brush:java;"> 在<接收器>元素需要在android:name屬性,它指定了應用程序的Widget使用的AppWidgetProvider。


在<意向filter>元素必須包含了Android的元素:name屬性。該屬性指定AppWidgetProvider接受ACTION_APPWIDGET_UPDATE播出。這是你必須顯式聲明的唯一播出。該AppWidgetManager自動發送所有其他App的Widget廣播到AppWidgetProvider是必要的。


在<元數據>元素指定AppWidgetProviderInfo資源,需要以下屬性:


機器人:名字 - 指定的元數據名稱。使用android.appwidget.provider標識數據作為AppWidgetProviderInfo描述符。
機器人:資源 - 指定AppWidgetProviderInfo資源位置。
添加AppWidgetProviderInfo元


該AppWidgetProviderInfo一個App Widget時,基本素質定義,如最小尺寸的布局,其初始布局資源,多久更新應用程序窗口小部件,和(可選)配置活動在創建時推出。定義AppWidgetProviderInfo對象使用一個元素的XML資源,並將其保存在項目的RES / XML /文件夾。


例如:


這裡的的摘要屬性:


對了minWidth和屬性了minHeight的值指定應用的Widget消耗默認的最小空間量。默認主頁屏幕位置應用小部件在其窗口的基礎上具有一個定義的高度和寬度的細胞的網格。如果一個App Widget的最小寬度或高度值不匹配的單元格的尺寸,然後應用程序窗口小部件的尺寸四捨五入到最接近的單元尺寸。
查看應用程序的Widget設計准則有關調整你的App小工具的更多信息。
注:為了使您的應用程序窗口小部件可跨設備,你的應用程序widget的最小尺寸不應大於4×4細胞。


該minResizeWidth和minResizeHeight屬性指定應用Widget的絕對最小尺寸。這些值應指定大小低於該應用的Widget會難以辨認或不可用。使用這些屬性允許用戶小窗口調整大小的尺寸可能比由了minWidth和了minHeight屬性定義的默認插件尺寸。在推出的Andr??oid 3.1。
查看應用程序的Widget設計准則有關調整你的App小工具的更多信息。
該updatePeriodMillis屬性定義多久的Widget應用程序框架應通過調用的onUpdate()回調方法要求從AppWidgetProvider更新。實際更新不保證准確地出現在時間這個值,我們則建議盡可能少,也許不超過一小時一次,以節省電池。您可能還允許用戶調整的頻率配置,有些人可能希望有一個股票代碼,以每15分鐘,或者也許只有一天四次更新。
注意:如果該裝置處於睡眠狀態時,它是時間的更新(如由updatePeriodMillis定義),則該設備將依次執行更新醒來。如果不更新超過每小時一次,這大概不會引起對電池壽命顯著問題。但是,如果您需要更新更頻繁和/或你並不需要更新,而設備是睡著了,那麼你就可以執行,而不是基於不會喚醒設備的報警的更新。要做到這一點,設置鬧鐘與你的AppWidgetProvider接收,使用AlarmManager的意圖。設置報警類型要麼ELAPSED_REALTIME或RTC,其中,當該設備是醒著將僅提供警報。然後設置updatePeriodMillis為零(“0”)。


該initialLayout屬性點來定義應用程序的Widget布局布局資源。
該配置屬性定義了活動,當用戶添加應用程序窗口小部件,為了推出他或她來配置應用程序窗口小部件的屬性。這是可選的(閱讀下面創建一個應用程序窗口小部件配置活動)。
該previewImage屬性指定的應用程序部件將是什麼它的配置後的預覽,選擇應用程序窗口小部件時,用戶看到。如果沒有提供,用戶,而不是看到你的應用程序的啟動圖標。該字段對應於Android的:在AndroidManifest.xml文件的<接收>元素previewImage屬性。對於使用previewImage的更多討論,請參閱設置預覽圖像。介紹了Android 3.0的。
該autoAdvanceViewId屬性指定的應用程序部件子視圖應該是自動先進的部件的主機的視圖ID。介紹了Android 3.0的。
該resizeMode屬性指定由一個widget可以調整的規則。您可以使用此屬性使主屏幕小部件可調整大小,水平,垂直或兩個軸。用戶觸摸按住某個小部件,以顯示其縮放柄,然後拖動水平和/或垂直手柄來改變布局網格的大小。對於resizeMode屬性的值包括“水平”,“垂直”和“無”。為調整大小水平和垂直聲明一個小部件,提供值“橫|縱”。在推出的Andr??oid 3.1。
該minResizeHeight屬性指定該控件可以調整的最低高度(DPS)。此字段沒有任何影響,如果超過了minHeight大於或沒有啟用垂直大小調整(見resizeMode)。介紹了Android 4.0的。
該minResizeWidth屬性指定了小部件可以調整大小的最小寬度(DPS)。此字段沒有任何影響,如果超過了minWidth大於或沒??有啟用水平調整大小(見resizeMode)。介紹了Android 4.0的。
該widgetCategory屬性聲明是否你的應用程序的Widget可以在主屏幕(home_screen),鎖屏(鍵盤保護),或者兩者上顯示。只有Android的版本比5.0的支持鎖屏小部件低。對於Android 5.0以上版本,只有home_screen是有效的。
見AppWidgetProviderInfo類由元素接受屬性的更多信息。


創建應用程序窗口小部件布局


你必須在XML定義一個初始布局為您的應用程序窗口小部件,並將其保存在項目的RES /布局/目錄下。您可以使用下面列出的視圖對象設計的App窗口小部件,但你開始設計的Widget應用程序之前,請閱讀並理解應用的Widget設計指南。


創建應用程序窗口小部件的布局很簡單,如果你熟悉的布局。但是,你必須要知道,應用程序的Widget布局是基於RemoteViews,這並不支持每一種布局或視圖小部件。


一個RemoteViews對象(,因此,應用程序的Widget),可以支持以下布局類:


的FrameLayout
的LinearLayout
的RelativeLayout
網格布局
而下面的小部件類:


AnalogClock
按鍵
時計
的ImageButton
ImageView的
進度條
TextView中
ViewFlipper
列表顯示
網格視圖
StackView
AdapterViewFlipper
不支持這些類的後裔。


RemoteViews還支持ViewStub,這是一種無形的,零大小的視圖,您可以使用在運行時懶洋洋地膨脹布局資源。


添加邊距應用小工具


窗口小部件,一般不應延伸到屏幕邊緣,不應該在視覺上與其他小部件齊平,所以你應該在你的周圍小窗口框各方增加利潤。


由於Android 4.0,應用小部件會自動給出的小窗口框和應用程序窗口小部件的邊框為用戶提供用戶的主屏幕上的其他部件和圖標更好地協調之間的填充。要充分利用這一強烈推薦行為的優勢,設置應用程序的targetSdkVersion至14或更大。


這很容易寫出具有適用於早期版本的平台,自定義邊距單一的布局,並有Android 4.0及更高沒有多余的邊距:


設置應用程序的targetSdkVersion至14或更大。
創建一個布局,如下面的人,引用其利潤率方面的資源:

<frameLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:padding="@dimen/widget_margin">

 

</frameLayout>
創建兩個維度的資源,一個在RES/價值/提供預Android 4.0的定制空間,和一個在res/值-V14/提供Android 4.0的小部件沒有微胖:
RES/價值/ dimens.xml:

8dp
res/values-v14/dimens.xml:

0dp
另一種選擇是簡單地在默認情況下建造額外的利潤到您的九宮背景的資產,並提供不同的九補丁沒有利潤率API級別14或更高版本。


使用AppWidgetProvider類


您必須聲明你的AppWidgetProvider類實現為使用在AndroidManifest的<接收器>元素的廣播接收器(參見清單聲明一個應用的Widget上面)。
在AppWidgetProvider類廣播接收器的方便類來處理應用程序的Widget廣播延伸。在AppWidgetProvider只接收事件廣播是相關的在App控件,當應用程序的Widget被更新,刪除,啟用和禁用等。當這些廣播事件發生時,AppWidgetProvider收到以下的方法調用:


的onUpdate()
這就是所謂的更新應用程序的Widget在由AppWidgetProviderInfo的updatePeriodMillis屬性定義的時間間隔(見添加AppWidgetProviderInfo元以上)。當用戶添加應用的Widget這種方法也被稱為,所以應該在必要時進行必要的設置,如定義事件處理程序的視圖和啟動一個臨時服務。但是,如果你已經聲明了一個配置活動,是不是當用戶添加應用程序窗口小部件,但呼吁後續更新調用此方法。它是配置活動時,配置完成後進行第一次更新的責任。 (請參閱下面創建一個應用程序窗口小部件配置活動。)
onAppWidgetOptionsChanged()
當小部件先放入這就是所謂的任何時間小部件大小。您可以使用此回調的基礎上的物件的尺寸范圍,以顯示或隱藏的內容。您可以通過調用getAppWidgetOptions(),它返回一個包,其中包括以下獲得尺寸范圍:


OPTION_APPWIDGET_MIN_WIDTH - 包含下界當前寬度,以dp為單位,一個widget實例。
OPTION_APPWIDGET_MIN_HEIGHT - 包含下界當前高度,以dp為單位,一個widget實例。
OPTION_APPWIDGET_MAX_WIDTH - 包含的上限在當前寬度,以dp為單位,一個widget實例。
OPTION_APPWIDGET_MAX_HEIGHT - 包含的上限在當前寬度,以dp為單位,一個widget實例。
這個回調是在API級別16(是Android 4.1)出台。如果實施此回調,請確保您的應用程序不依賴於它,因為它不會對舊設備進行調用。
onDeleted(上下文,INT [])
這就是所謂的每一個App的Widget從應用的Widget主機中刪除的時間。
onEnabled(上下文)
當一個實例的應用程序的widget被首次創造了這個被調用。例如,如果用戶將您的Widget應用程序的兩個實例,這只是所謂的第一次。如果您需要打開一個新的數據庫或進行其他設置只需要為所有App控件實例出現一次,那麼這是一個很好的地方去做。
onDisabled(上下文)
當你的應用的Widget的最後一個實例是從應用的Widget主機中刪除這就是所謂的。這是你應該清理onEnabled(上下文)所做的任何工作,如刪除臨時數據庫。
的onReceive(上下文,意圖)
這被稱為用於每個廣播和上述各回調方法之前。你通常不需要,因為默認的AppWidgetProvider實現過濾所有App的Widget廣播並調用上面的方法適當實現此方法。
最重要的AppWidgetProvider回調的onUpdate(),因為當每個應用程序窗口小部件添加到主機(除非你使用一個配置Activity)的叫法。如果你的應用程序的Widget接受任何用戶交互事件,那麼你需要在這個回調注冊事件處理程序。如果你的應用的Widget不創建臨時文件或數據庫,或執行需要清理,然後其他的onUpdate工作()可能是你需要定義的唯一回調方法。例如,如果你想要一個應用程序widget工具點擊時啟動一個活動的一個按鈕,你可以使用下面的實現AppWidgetProvider的:

public class ExampleAppWidgetProvider extends AppWidgetProvider {

  public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    final int N = appWidgetIds.length;

    // Perform this loop procedure for each App Widget that belongs to this provider
    for (int i=0; i
這AppWidgetProvider定義了用於定義啟動一個活動的PendingIntent,並與setOnClickPendingIntent(INT,的PendingIntent)連接到App Widget的按鈕的目的只有的onUpdate()方法。請注意,它包含一個循環,通過appWidgetIds每個條目,這是確定此提供程序創建的每個應用程序的Widget ID數組進行迭代。以這種方式,如果用戶創建的應用程序的widget的多個實例,則它們都同時更新。但是,只有一個updatePeriodMillis時間表將用於應用程序的widget的所有實例進行管理。例如,如果更新時間表被定義為每兩個小時,和App小工具的第二個實例是第一個之後添加一小時後,他們都將在由第一和第二更新所定義的周期來更新期間將被忽略(他們都會進行每兩小時不每小時更新一次)。


注意:因為AppWidgetProvider是廣播接收器的擴展,你的進程不能保證繼續運行,回調方法返回後(見的BroadcastReceiver關於廣播生命周期信息)。如果你的應用的Widget安裝過程可能需要幾秒鐘(也許當執行網頁請求),你需要你的進程繼續,考慮在的onUpdate()方法啟動服務。從服務中,您可以不用擔心AppWidgetProvider收盤下跌,由於應用程序執行自己的更新到App控件不響應(ANR)錯誤。參見維基樣品的AppWidgetProvider運行服務一個App的Widget的例子。


另請參閱ExampleAppWidgetProvider.java示例類。


接收應用的Widget廣播意圖


AppWidgetProvider只是一個方便的類。如果您想直接接收應用的Widget廣播,你可以實現自己的BroadcastReceiver或者重寫的onReceive(上下文,意圖)回調。你需要關心的意圖如下:


ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED
創建應用程序窗口小部件配置活動


如果您想用戶配置設置時,他或她增加了一個新的Widget應用程序,你可以創建一個應用程序的Widget配置活動。本次活動將通過應用程序的Widget主機自動啟動,並允許用戶在配置創建時間為App的Widget可用的設置,如應用程序的Widget顏色,尺寸,更新周期或其他功能的設置。


配置活動應該被聲明為Android清單文件中的正常活動。但是,它將被應用的Widget主機與ACTION_APPWIDGET_CONFIGURE行動推出,所以活動需要接受這個意圖。例如

  
    
  
(見添加AppWidgetProviderInfo元以上)配置屬性:此外,活動必須在AppWidgetProviderInfo XML文件中聲明,與Android。例如,配置活動可以聲明如下:


請注意,該活動是聲明的完全限定的命名空間,因為它會從你的包范圍內引用。
這就是所有你需要開始使用的配置活動。現在,所有你需要的是實際的活動。有,但是,當你實現了活動的兩個重要的事情要記住:
該應用程序的Widget宿主調用配置活動以及配置活動應該總是返回一個結果。結果應該包括由發起的活動(保存在Intent作為額外EXTRA APPWIDGETID)的意圖傳遞的應用程序窗口小部件ID。
在創建應用程序窗口小部件時(當配置活動推出的系統將不會發送ACTION APPWIDGET_UPDATE廣播)的的onUpdate()方法將不會被調用。它是配置活動的責任從AppWidgetManager請求更新第一次創建應用程序窗口小部件時。然而,的onUpdate()將被要求對後續更新,它只是跳過第一次。
請參閱下一節的代碼片段如何從配置返回結果和更新應用的Widget的例子。
從配置活動更新應用的Widget
當一個應用程序的Widget使用配置的活動,這是活動的責任來更新應用程序窗口小部件時配置完成。您可以直接從AppWidgetManager請求更新這麼做。
下面就來正確地更新應用程序窗口小部件並關閉配置活動的程序的摘要:
首先,獲得從發射活動的意圖應用的Widget ID:

Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
  mAppWidgetId = extras.getInt(
      AppWidgetManager.EXTRA_APPWIDGET_ID, 
      AppWidgetManager.INVALID_APPWIDGET_ID);
}
執行你的App小部件配置。
當配置完成後,通過調用的getInstance(上下文)獲得AppWidgetManager的實例:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
Update the App Widget with aRemoteViewslayout by callingupdateAppWidget(int, RemoteViews):

RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
  1. Finally, create the return Intent, set it with the Activity result, and finish the Activity:
    Intent resultValue = new Intent();
    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
    setResult(RESULT_OK, resultValue);
    finish();
    提示:當您的配置活動第一次打開,設置活動結果RESULT_CANCELED。這樣一來,如果用戶備份出活動的到達結束之前,應用的Widget通知主機的配置被取消和App的Widget將不能添加。


    見ApiDemos的ExampleAppWidgetConfigure.java示例類的例子。


    設置預覽圖像


    Android 3.0的推出previewImage領域,它指定什麼樣的應用程序窗口小部件看起來像一個預覽。此預覽被示出為從微件選擇器的用戶。如果沒有提供這個領域,應用Widget的圖標用於預覽。


    這是你如何指定XML此設置

    
    為了幫助您的應用程序窗口小部件(指定預覽圖像場)創建一個預覽圖像,Android模擬器包括稱為應用程序“窗口小部件預覽”。要創建一個預覽圖像,啟動這個應用程序,選擇您的應用程序應用程序窗口小部件,並將它設置你喜歡你們的預覽圖像出現,然後將其保存,並將其放置在應用程序的繪圖資源。
    使用App窗口小部件與收藏
    Android 3.0的推出應用小部件與集合。這些種類的應用程序的窗口小部件的使用RemoteViewsService來顯示由遙控數據,如從內容提供商備份集合。由RemoteViewsService提供的數據呈現在使用下面的視圖類型,我們將把為一體的應用程序部件“收集的意見:”
    列表顯示
    這顯示了垂直滾動列表項的視圖。舉一個例子,看看Gmail應用程序部件。
    網格視圖
    這顯示了在二維滾動網格項目的視圖。舉一個例子,看到書簽應用部件。
    StackView
    一種堆疊卡片視圖(有點像一個關系網,),在這裡用戶可以輕彈前卡上/下看到一個/下一個卡,分別為。例子包括YouTube和圖書應用的部件。
    AdapterViewFlipper
    適配器支持簡單ViewAnimator兩個或多個視圖之間動畫。只有一個孩子,顯示在一段時間。
    如上所述,這些收集的意見顯示由遠程數據支持的集合。這意味著,他們使用適配器將其用戶界面綁定到他們的數據。適配器結合從一組數據成單個視圖對象的單個項目。由於這些收集的意見是通過適配器支持,Android框架必須包括額外的架構,支持應用小部件的使用。在一個應用程序widget的背景下,適配器是由RemoteViewsFactory,這簡直就是圍繞適配器接口的瘦包裝所取代。當集合中要求特定項目時,RemoteViewsFactory創建並返回該項目的集合作為一個RemoteViews對象。為了在您的應用程序窗口小部件集合視圖,您必須實現RemoteViewsService和RemoteViewsFactory。
    RemoteViewsService是一種服務,它允許遠程適配器請求RemoteViews對象。 RemoteViewsFactory是一個集合視圖之間的適配器,該視圖的基礎數據的接口(如ListView中,GridView的,等等)和。從StackView的Widget樣本,這裡是你用來實現這個服務和接口的樣板代碼的例子:

    public class StackWidgetService extends RemoteViewsService {
      @Override
      public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
      }
    }
    
    class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
    
    //... include adapter-like methods here. See the StackView Widget sample.
    
    }
    示例應用程序
    本節中的代碼摘錄從StackView控件樣品得出:

    \

    該樣本包括10次,其中顯示值棧的“0”!到“9”!示例應用程序部件有這些主要行為:


    用戶可以垂直甩在應用程序插件的頂視圖來顯示一個或下一個視圖。這是一個內置StackView行為。
    無需任何用戶交互,應用小工具會自動通過其在序列意見的進步,像幻燈片。這是由於設置的android:在res / XML / stackwidgetinfo.xml文件autoAdvanceViewId =“@ ID / stack_view”。此設置適用於該視圖的ID,在這種情況下是堆棧視圖的視圖ID。
    如果用戶觸摸的頂視圖,該應用插件播放吐司消息“已觸摸視圖N,”,其中n是被觸摸的視圖的索引(位置)。對於這是如何實現的更多討論,請參見添加行為的個別項目。
    實施與應用的集合小工具


    為了實現與集合的應用程序插件,你按照你會用它來實現任何應用程序插件的相同的基本步驟。以下各節介紹您需要執行來實現與集合的應用程序插件的額外步驟。


    清單與集合應用小工具


    除了聲明中的清單應用程序窗口小部件列出的要求,使其能夠用於收藏的應用程序部件綁定到你的RemoteViewsService,您必須在使用許可BIND_REMOTEVIEWS您的清單文件中聲明該服務。這可以防止其他應用程序訪問任意你的應用程序widget的數據。例如,創建一個使用RemoteViewsService來填充集合視圖一個App窗口小部件時,清單條目可能是這樣的:

    該生產線機器人:名字=“MyWidgetService”指的是你RemoteViewsService的子類。
    布局與集合應用小工具
    為您的應用程序部件的布局XML文件的主要要求是,它包括收集意見之一:ListView中,GridView控件,StackView或AdapterViewFlipper。下面是StackView樣品的Widget小部件layout.xml:

    
    
    <frameLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      
      
    </frameLayout>
    需要注意的是空的意見必須是其空視圖表示空狀態集合視圖的兄弟姐妹。


    除了布局文件為您的整個應用程序窗口小部件,您必須創建定義布局集合中的每個項目另一個布局文件(例如,每本書的藏書在布局)。例如,StackView的Widget樣品僅具有一個布局文件,widget_item.xml,由於所有的項目使用相同的布局。但是WeatherListWidget樣品有兩個布局文件:dark_widget_item.xml和light_widget_item.xml。


    對於集合應用小部件AppWidgetProvider類


    與普通的應用小工具,在你的AppWidgetProvider子類的大量代碼通常進去的onUpdate()。在實施的onUpdate的主要區別創建帶有集合一個應用程序窗口小部件時()是你必須調用setRemoteAdapter()。這告訴集合視圖從哪裡得到它的數據。然後RemoteViewsService可以回到你的RemoteViewsFactory實施,和小部件能容納相應的數據。當你調用這個方法,你必須通過一個指向您的實現RemoteViewsService,並指定應用程序窗口小部件更新的應用小部件ID的意圖。


    例如,這裡的StackView的Widget樣本是如何實現的onUpdate()回調方法來設置RemoteViewsService為應用程序部件集合遠程適配器:

    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
    int[] appWidgetIds) {
      // update each of the app widgets with the remote adapter
      for (int i = 0; i < appWidgetIds.length; ++i) {
        
        // Set up the intent that starts the StackViewService, which will
        // provide the views for this collection.
        Intent intent = new Intent(context, StackWidgetService.class);
        // Add the app widget ID to the intent extras.
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
        // Instantiate the RemoteViews object for the app widget layout.
        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
        // Set up the RemoteViews object to use a RemoteViews adapter. 
        // This adapter connects
        // to a RemoteViewsService through the specified intent.
        // This is how you populate the data.
        rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
        
        // The empty view is displayed when the collection has no items. 
        // It should be in the same layout used to instantiate the RemoteViews
        // object above.
        rv.setEmptyView(R.id.stack_view, R.id.empty_view);
    
        //
        // Do additional processing specific to this app widget...
        //
        
        appWidgetManager.updateAppWidget(appWidgetIds[i], rv);  
      }
      super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
    RemoteViewsService類


    堅持數據


    你不能靠你的服務,或者包含任何數據的單個實例,堅持。因此,應該沒有任何數據存儲在您的RemoteViewsService(除非它是靜態的)。如果你希望你的應用程序widget的數據依然存在,最好的辦法是使用的ContentProvider其數據持續超過流程生命周期。
    如上所述,你RemoteViewsService子類提供用於填充遠程集合視圖的RemoteViewsFactory。


    具體來說,您需要執行以下步驟:


    子類RemoteViewsService。 RemoteViewsService是通過一個遠程適配器可以請求RemoteViews服務。
    在RemoteViewsService子類,包括實現RemoteViewsFactory接口的類。 RemoteViewsFactory為遠程集合視圖之間的適配器該視圖的基礎數據的接口(如ListView中,GridView的,等等),並。你的實現是負責制定一個RemoteViews對象數據集中的每個項目。這個接口是圍繞適配器瘦包裝。
    所述RemoteViewsService執行情況的主要內容是其RemoteViewsFactory,如下所述。


    RemoteViewsFactory接口


    實現RemoteViewsFactory界面自定義類提供了其集合中的項目的數據應用程序部件。要做到這一點,它結合了您的應用程序部件項目XML布局文件與數據源。數據的這個源可以是來自一個數據庫的任何一個簡單陣列。在StackView的Widget樣本,所述數據源是WidgetItems的陣列。該RemoteViewsFactory用作適配器連接到數據膠水遠程采集視圖。


    你需要實現你的RemoteViewsFactory子類的兩個最重要的方法是的onCreate()和getViewAt()。


    系統調用的onCreate創建工廠的第一次時,()。這是你設置的任何連接和/或光標到數據源。例如,StackView的Widget示例使用的onCreate()來初始化WidgetItem對象的數組。當你的應用程序widget是積極的,系統訪問這些對象使用數組和它們所包含的文本中的索引位置顯示


    下面是從StackView的Widget樣品的RemoteViewsFactory實施,顯示了onCreate()方法的部分摘錄:

    class StackRemoteViewsFactory implements
    RemoteViewsService.RemoteViewsFactory {
      private static final int mCount = 10;
      private List mWidgetItems = new ArrayList();
      private Context mContext;
      private int mAppWidgetId;
    
      public StackRemoteViewsFactory(Context context, Intent intent) {
        mContext = context;
        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
      }
    
      public void onCreate() {
        // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
        // for example downloading or creating content etc, should be deferred to onDataSetChanged()
        // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
        for (int i = 0; i < mCount; i++) {
          mWidgetItems.add(new WidgetItem(i + "!"));
        }
        ...
      }
    ...
    所述RemoteViews工廠方法getView()返回在數據集中的指定位置相對應的數據的RemoteViews對象。下面是從StackView的Widget樣品的RemoteViewsFactory實現的摘錄:

    public RemoteViews getViewAt(int position) {
     
      // Construct a remote views item based on the app widget item XML file, 
      // and set the text based on the position.
      RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
      rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
    
      ...
      // Return the remote views object.
      return rv;
    }
    添加行為,個別項目


    上述部分介紹如何將數據綁定到你的應用程序窗口小部件的集合。但是,如果你想做的動態行為添加到您的收藏視圖中的單個項目?


    如使用AppWidgetProvider類描述,通常使用setOnClickPendingIntent()來設置對象的點擊行為,如造成一個按鈕啟動一個活動。但是,這種做法是不允許在單獨的一個集合項目??子視圖(澄清,你可以使用setOnClickPendingIntent()設置在啟動應用程序,例如Gmail應用程序部件一個全球性的按鈕,但不是各列表項)。相反,添加一個集合中點擊行為向單個項目,您使用setOnClickFillInIntent()。這就需要建立一個未決的意圖模板您的收藏視圖,然後對每個項目集合中通過您的RemoteViewsFactory設置填充的意圖。


    本節使用的Widget StackView樣本來描述如何添加行為的個別項目。在StackView的Widget樣品,如果用戶觸摸的頂視圖,該應用插件播放吐司消息“已觸摸視圖N,”,其中n是被觸摸的視圖的索引(位置)。這是它的工作原理:


    該StackWidgetProvider(一個AppWidgetProvider子類)創建待意圖有一個名為TOAST_ACTION自定義操作。
    當用戶觸摸視圖,意圖被觸發,它廣播TOAST_ACTION。
    此廣播是由StackWidgetProvider的的onReceive()方法攔截,以及應用程序插件播放了感動視圖敬酒消息。對於集合的項目中的數據是由RemoteViewsFactory經由RemoteViewsService提供。
    注:StackView的Widget示例使用廣播,但通常一個應用程序窗口小部件只會在類似這樣的情況下推出的一項活動。


    設置掛起意圖模板


    該StackWidgetProvider(AppWidgetProvider子類)建立了一個懸而未決的意圖。集合個人物品不能建立自己的未決意圖。取而代之的是,集合作為一個整體設置了一個待處理的意圖模板,並且單個項目設置填充在意圖上創建一個項目逐個項目基礎的獨特的行為。


    這個類還接收當用戶觸摸一個觀點,即發送廣播。它在它的onR??eceive()方法處理此事件。如果意圖的行動是TOAST_ACTION,應用程序插件播放當前視圖敬酒消息

    public class StackWidgetProvider extends AppWidgetProvider {
      public static final String TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION";
      public static final String EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM";
    
      ...
    
      // Called when the BroadcastReceiver receives an Intent broadcast.
      // Checks to see whether the intent's action is TOAST_ACTION. If it is, the app widget 
      // displays a Toast message for the current item.
      @Override
      public void onReceive(Context context, Intent intent) {
        AppWidgetManager mgr = AppWidgetManager.getInstance(context);
        if (intent.getAction().equals(TOAST_ACTION)) {
          int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
          int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);
          Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show();
        }
        super.onReceive(context, intent);
      }
      
      @Override
      public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // update each of the app widgets with the remote adapter
        for (int i = 0; i < appWidgetIds.length; ++i) {
      
          // Sets up the intent that points to the StackViewService that will
          // provide the views for this collection.
          Intent intent = new Intent(context, StackWidgetService.class);
          intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
          // When intents are compared, the extras are ignored, so we need to embed the extras
          // into the data so that the extras will not be ignored.
          intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
          RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
          rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
      
          // The empty view is displayed when the collection has no items. It should be a sibling
          // of the collection view.
          rv.setEmptyView(R.id.stack_view, R.id.empty_view);
    
          // This section makes it possible for items to have individualized behavior.
          // It does this by setting up a pending intent template. Individuals items of a collection
          // cannot set up their own pending intents. Instead, the collection as a whole sets
          // up a pending intent template, and the individual items set a fillInIntent
          // to create unique behavior on an item-by-item basis.
          Intent toastIntent = new Intent(context, StackWidgetProvider.class);
          // Set the action for the intent.
          // When the user touches a particular view, it will have the effect of
          // broadcasting TOAST_ACTION.
          toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);
          toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
          intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
          PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
          rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);
          
          appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
        }
      super.onUpdate(context, appWidgetManager, appWidgetIds);
      }
    }
    設置填充式意圖


    您RemoteViewsFactory必須在集合中的每個項目設定一個填空題意圖。這使得可以區分個體上點擊特定項目的動作。在填充在意圖然後,以確定被點擊的項目時,將要執行的最終意圖與的PendingIntent模板相結合。

    public class StackWidgetService extends RemoteViewsService {
      @Override
      public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
      }
    }
    
    class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
      private static final int mCount = 10;
      private List mWidgetItems = new ArrayList();
      private Context mContext;
      private int mAppWidgetId;
    
      public StackRemoteViewsFactory(Context context, Intent intent) {
        mContext = context;
        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
      }
    
      // Initialize the data set.
        public void onCreate() {
          // In onCreate() you set up any connections / cursors to your data source. Heavy lifting,
          // for example downloading or creating content etc, should be deferred to onDataSetChanged()
          // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
          for (int i = 0; i < mCount; i++) {
            mWidgetItems.add(new WidgetItem(i + "!"));
          }
         ...
        }
        ...
      
        // Given the position (index) of a WidgetItem in the array, use the item's text value in 
        // combination with the app widget item XML file to construct a RemoteViews object.
        public RemoteViews getViewAt(int position) {
          // position will always range from 0 to getCount() - 1.
      
          // Construct a RemoteViews item based on the app widget item XML file, and set the
          // text based on the position.
          RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
          rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
      
          // Next, set a fill-intent, which will be used to fill in the pending intent template
          // that is set on the collection view in StackWidgetProvider.
          Bundle extras = new Bundle();
          extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
          Intent fillInIntent = new Intent();
          fillInIntent.putExtras(extras);
          // Make it possible to distinguish the individual on-click
          // action of a given item
          rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
        
          ...
        
          // Return the RemoteViews object.
          return rv;
        }
      ...
      }
    保持收集數據新鮮


    下圖說明了發生在更新時使用集合的應用程序插件的流量。它顯示了應用程序部件代碼如何與RemoteViewsFactory互動,以及如何觸發更新


    使用集合應用小部件的一個特點是,為用戶提供了最新的內容。例如,考慮到Android 3.0的Gmail應用小工具,它為用戶提供他們的收件箱的快照。要做到這一點,你需要能夠觸發RemoteViewsFactory和收集,以獲取並顯示新的數據。您的通話AppWidgetManager實現這一notifyAppWidgetViewDataChanged()。此調用生成一個回調到您RemoteViewsFactory的onDataSetChanged()方法,它讓你有機會獲取任何新數據。請注意,您可以內onDataSetChanged()回調同步執行處理密集型操作。你保證,之前的元數據或顯示數據是從RemoteViewsFactory獲取此調用將完成。此外,可以將getViewAt()方法中進行處理密集型操作。如果該調用需要很長的時間,加載視圖(由RemoteViewsFactory的getLoadingView()方法指定),將顯示在集合視圖,直到它返回的相應位置。




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