android widget包說明與應用

來源:互聯網
上載者:User

標籤:

widget包是存放自訂群組件

開發自訂群組件;

其實Android API開發指南中的App Widgets章節 已經說得很清楚了,下面只是對自己的理解進行一次梳理。 

-- 
AppWidget 就是HomeScreen上顯示的小組件,提供直觀的互動操作。通過在HomeScreen中長按,在彈出的對話方塊中選擇Widget組件來進行建立,長按組件後並拖動到垃圾箱裡進行刪除。同一個Widget組件可以同時建立多個。 

AppWidget的實現主要涉及到以下類: 
AppWidgetProvider 
RemoteViews 
AppWidgetManager 

1. 
首先需要提供一個定義了Widget介面布局的XML檔案(位於res/layout/..),需要注意的是使用的組件必須是RemoteViews所支援的,目前原生API中支援的組件如下: 
FrameLayout 
LinearLayout 
RelativeLayout 

AnalogClock 
Button 
Chronmeter 
ImageButton 
ImageView 
ProgressBar 
TextView 

*如果使用了除此之外的組件,則在Widget建立時會導致android.view.InflateExceptionn異常。 

PS:這就導致有一些功能或樣式無法實現,如很基本的list或文本編輯框都是無法直接實現的。如果想自訂Widget中的View的話只能通過修改framework來提供相應組件的支援。 

2. 
然後需要提供一個xml檔案來定義Widget的基本屬性,放置到res/xml/..目錄下。 
如果使用的是Eclipse可按如下操作: 
1) 在res/目錄下建立xml/目錄 
2)建立xml檔案(名字可任意),選擇類型為AppWidgetProvider 
3)在彈出的便捷介面進行參數設定 

主要設定的參數如下: 
minWidth: 定義Wdiget組件的寬度 
minHeight: 定義Wdiget組件的高度 
updatePeriodMillis: 更新的時間周期 
initialLayout: Widget的布局檔案 
configure: 如果需要在啟動前先啟動一個Activity進行設定,在這裡給出Activity的完整類名(後面會說到,與一般Activity的實現有些許差別) 

*Widget大小的計算儲存格數*74)-2,API上說是為了防止像素計算時的整數舍入導致錯所以-2...不是很明白 

一個完整的範例: 
Xml代碼  收藏代碼 

    <?xml version="1.0" encoding="utf-8"?>  
    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  
          android:minWidth="80dp"  
          android:minHeight="32dp"  
          android:updatePeriodMillis="86400000"  
          android:initialLayout="@layout/widget_provider"  
          android:configure="com.demo.widget.MyWidgetConfiguration" >  
    </appwidget-provider>  



3. 
xml都定義好後,接下來就是建立一個繼承自AppWidgetProvider的子類,AppWidgetProvider實際上就是一個BroadcastReceiver,裡面提供了以下函數: 
onReceive(Context, Intent) 
onUpdate(Context , AppWidgetManager, int[] appWidgetIds) 
onEnabled(Context) 
onDeleted(Context, int[] appWidgetIds) 
onDisabled(Context) 
可通過重寫以上函數來監聽Widget狀態的變化並進行相應的處理。 

以上函數具體調用情況歸納如下: 
[啟動 - 無confiure Activity] 
onReceive 
onEnabled —— 第一個widget被顯示 
onReceive 
onUpdate —— 重新整理介面 

[啟動 - 帶confiuration Activity] 
onReceive 
onUpdate 

[拖動] 
<無狀態變化> 

[周期更新] 
onReceive 
onUpdate 

[刪除] 
onReceive 
onDeleted —— widget被刪除 
onReceive 
onDisabled —— 最後一個widget被移除 

[啟動時位置不夠] 
onReceive 
onEnabled 
onReceive 
onUpdate 
onReceive 
onDeleted 
onReceive 
onDisabled 

*每次狀態的變化會觸發onReceive,一般該函數是不需要重寫的。 

簡單瞭解AppWidgetProvider之後,我們來看具體實現。 
這裡建立一個MyAppWidgetProvider繼承AppWidgetProvider: 
Java代碼  收藏代碼 

    public class MyWidgetProvider extends AppWidgetProvider {  
      
          static final String TAG = "widget";  
           
          /** 
           * 更新 
           */  
          public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){  
                Log.i(TAG, "onUpdate");  
          }  
           
          /** 
           * 第一個Widget組件啟動時觸發 
           */  
          public void onEnabled(Context context){  
                Log.i(TAG, "onEnabled");  
          }  
           
          /** 
           * 最後一個Widget組件關閉時觸發 
           */  
          public void onDisabled(Context context){  
                Log.i(TAG, "onDisabled");  
          }  
           
          /** 
           * 任一Widget組件被刪除時觸發 
           */  
          public void onDeleted(Context context, int[] appWidgetIds){  
                Log.i(TAG, "onDeleted");  
          }  
           
          /** 
           * 以上函數觸發前會先觸發該函數,一般不需要重寫 
           */  
          public void onReceive(Context context, Intent intent){  
                Log.i(TAG, "onReceive");  
                super.onReceive(context, intent);  
          }  
           
    }  



其中onUpdate顧名思義是對Widget進行更新的,前面定義的更新周期就是作用於該函數的。 
Widget的更新與Activity不同,必須藉助於RemoteViews和AppWidgetMananger。具體實現如下: 
Java代碼  收藏代碼 

    public void onUpdate(Context context, AppWidgetMananger appWidgetManager, int[] appWidgetIds){  
        int N = appWidgetIds.length; // 可能啟動了多個Widget,appWidgetIds記錄了這些Widget的ID  
        for(int i=0; i<N; i++){  
            RemoteViews  views = new RemoteViews(getPackageName(), R.layout.widget_views);  
            appWidgetManager.updateAppWidget(appWidgetIds[i], views);  
        }  
    }  


其中需要注意的是,雖然RemoteViews參數都是一樣的,但是對於每個Widget最好都新建立一個再進行傳遞,否則會導致一些錯誤。具體可參考AppWidget RemoteViews 記憶體溢出 。 

其他函數的可以根據需要實現。 

由於無法擷取到RemoteViews建立的介面中的元素,對於Widget中組件的操作只能通過RemoteViews所提供的有限的函數進行,常用的有: 
setOnClickPendingIntent(int viewId, PendingIntent pendingIntent) 
setProgressBar(int viewId, int max, int progress, boolean indeterminate) 
setTextViewText(int viewId, CharSequence text) 
setViewVisibility(int viewId, int visibility) 
詳細函數列表可參考API中的RemoteViews類 。 

4. 
最後,更新AndroidManifest.xml。 
AppWidgetProvider對應一個receiver屬性: 
Xml代碼  收藏代碼 

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



5. 
提供Configuration Activity 
Configuration Activity是一個在Widget啟動前先啟動的Activity,方便使用者對Widget的屬性進行設定。 

在res/xml/...下對應的"屬性檔案"中添加configure欄位指定啟動的Activity,並在AndroidManifest.xml中該Activity下提供一個action為android.appwidget.action.APPWIDGET_CONFIGURE 的IntenFilter。 

需要注意的是, 
如果設定了Configure屬性,則必須在指定的Activity中進行如下處理: 
1.在onCreate中setContentView()函數前添加setResult(RESULT_CANCLE) ,這樣如果在Activity初始化完成前按下了BACK按鍵,則Widget不會啟動; 
2.在setContentView()函數之後(不一定要在onCreate中,在Activity退出前即可),添加如下設定以指定需要啟動的Widget: 
Java代碼  收藏代碼 

    int mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);  
    Intent resultValue = new Intent();  
    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);  
    setResult(RESULT_OK, resultValue);  

否則會導致退出Activity後Widget不啟動。 

>> Widget建立步驟匯總: 
1.定義Widget布局XML -> res/layout/... 
2.定義Widget屬性檔案(xml) -> res/xml/... 
3. 建立AppWidgetProider子類,實現onUpdate()等函數,在manifest中註冊receiver,添加一個action為 android.appwidget.action.APPWIDGET_UPDATE 的IntentFilter,並添加如下<meta- data>標識: 
Xml代碼  收藏代碼 

    <meta-data android:resource="@xml/<屬性檔案xml>" android:name="android.appwidget.provider"></meta-data>  



4. 建立Coniguration Activity(注意處理好setResult),添加到屬性檔案中的Configure屬性,在manifest中註冊activity,添加一個 action為android.appwidget.action.APPWIDGET_CONFIGURE 的IntentFilter 

最後附上一個完整的例子, 
實現思路如下: 
1. 提供一個Configuration Activity,這裡只簡單顯示一行文字; 
2.退出後Widget啟動; 
3.點擊Widget中的按鈕會啟動一個Activity

(轉自:http://quding0308.iteye.com/blog/1164276)

android widget包說明與應用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.