Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 轉 比較好的widget講解

android 轉 比較好的widget講解

編輯:關於Android編程

1.創建AppWidget布局,包含兩個TextView用來顯示內容:  Xml代碼   <?xml version="1.0" encoding="utf-8"?>   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"       android:layout_width="fill_parent" android:layout_height="fill_parent"       android:orientation="vertical">       <TextView android:layout_height="wrap_content"           android:layout_width="fill_parent" android:id="@+id/tv1"           android:textColor="#FF0000" android:textSize="24sp" android:textStyle="bold"           android:text="-1"></TextView>       <TextView android:layout_height="wrap_content" android:id="@+id/tv2"           android:textSize="24sp" android:textStyle="bold" android:textColor="#00FF00"           android:layout_width="fill_parent" android:text="-2"></TextView>   </LinearLayout>     2.在res下創建xml目錄,再在xml目錄裡面創建AppWidget信息xml文件:  2.1新建xml文件時,type選擇AppWidget Provider。      2.2填充屬性:    寬高的計算公式為:占用屏幕格數*74-2  Update period millis:設置為0,手動刷新。根據實驗,設置不為0時,至少在2.2上系統根本不按照設置的值刷新,還是自己控制刷新時機好了。  Initial layout:就添控件要使用的布局。  Configure暫時不用,留空。  3.創建AppWidgetDemo類:    重載AppWidgetProvider中的所有函數,每個函數裡面增加輸出語句,以查看調用順序。  Java代碼   public class AppWidgetDemo extends AppWidgetProvider {          @Override       public void onDeleted(Context context, int[] appWidgetIds) {           // TODO Auto-generated method stub           super.onDeleted(context, appWidgetIds);           Log.e("AppWidgetDemo", "onDeleted");       }          @Override       public void onDisabled(Context context) {           // TODO Auto-generated method stub           super.onDisabled(context);           Log.e("AppWidgetDemo", "onDisabled");       }          @Override       public void onEnabled(Context context) {           // TODO Auto-generated method stub           super.onEnabled(context);           Log.e("AppWidgetDemo", "onEnabled");       }          @Override       public void onReceive(Context context, Intent intent) {           // TODO Auto-generated method stub           super.onReceive(context, intent);           Log.e("AppWidgetDemo", "onReceive,Action:" + intent.getAction());       }          @Override       public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {           // TODO Auto-generated method stub           super.onUpdate(context, appWidgetManager, appWidgetIds);           Log.e("AppWidgetDemo", "onUpdate,Count:" + appWidgetIds.length);       }      }     4.在AndroidManifest.xml文件中聲明此Widget:  添加一個Receiver,其name為AppWidgetDemo類的類名。  Xml代碼   <receiver android:name="AppWidgetDemo"></receiver>     為此Receiver添加Intent filter,接收系統發出android.appwidget.action.APPWIDGET_UPDATE的Intent。  Xml代碼   <receiver android:name="AppWidgetDemo">       <intent-filter>           <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>       </intent-filter>             </receiver>     此外還要為此receiver添加meta-data信息,以告知系統相關的AppWidgetProvider信息:  Xml代碼   <meta-data android:name="android.appwidget.provider"                   android:resource="@xml/widget_info_demo"></meta-data>     meta-data的name是約定好的android.appwidget.provider,resource則是第2步創建的AppWidget信息xml文件。    5.至此AppWidget已經可用了,安裝到模擬器上看下運行流程。  5.1添加一個Widget到桌面上:  onEnabled被呼叫:按照說明,當桌面上出現第一個此Widget的實例時,此函數被呼叫。  onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_ENABLED  onUpdate被呼叫:onUpdate,Count:1,並且待更新的AppWidget數量為1  onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_UPDATE    5.2再添加一個Widget到桌面上:  onUpdate被呼叫:onUpdate,Count:1,並且待更新的AppWidget數量仍然為1,而不是2。  onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_UPDATE    5.3從桌面上移除一個Widget:  onDeleted:每個實例被移除時都會被呼叫  onReceive,Action:android.appwidget.action.APPWIDGET_DELETED    5.4再從桌面上移除一個Widget:  onDeleted:仍然執行  onReceive,Action:android.appwidget.action.APPWIDGET_DELETED  onDisabled:因為是最後一個活動的實例被移除了,所以被呼叫。  onReceive,Action:android.appwidget.action.APPWIDGET_DISABLED    6.刷新AppWidget  6.1在onUpdate()中刷新:  onUpdate在AppWidget放到桌面時會被調用,在Update period millis達到時可能會被調用。  Java代碼   RemoteViews appWidgetView = new RemoteViews(context.getPackageName(), R.layout.widget_layout_demo);   appWidgetView.setTextViewText(R.id.tv1, String.valueOf(mCount));   appWidgetView.setTextViewText(R.id.tv2, String.valueOf(mCount));   appWidgetManager.updateAppWidget(appWidgetIds, appWidgetView);     先獲取一個RemoteViews,也就是AppWidget的布局所對應的View;  使用指定的Id更新要更新的控件;  更新整個RemoteViews,此時就可以更新AppWidget內容了。    但是這樣的代碼還有一個問題,當向桌面依次添加多個控件時會出現下面這樣的效果:    即更新時沒有同時更新所有的AppWidget,這是因為onUpdate中傳進來的數組中只包含了1個id,如果想同時更新多個,那麼可以把更新語句更換為:  Java代碼   appWidgetManager.updateAppWidget(new ComponentName(context, AppWidgetDemo.class), appWidgetView);     通過組件名可以把所有的名字符合的AppWidget都更新。    6.2在onReceive()中更新  6.2.1自定義Action通知刷新:  在AndroidManifest.xml中定義的receiver的intent-filter增加一個自定義的Action:  com.demo.appwidget.refresh  Xml代碼    <receiver android:name="AppWidgetDemo">   <intent-filter>       <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>       <action android:name="com.demo.appwidget.refresh"></action>   </intent-filter>   <meta-data android:name="android.appwidget.provider"       android:resource="@xml/widget_info_demo"></meta-data>   lt;/receiver>     包含此Action的Intent可以在後台服務或者Activity中發出,然後會被此Receiver接收,進而觸發onReceive。  本例中采用按鈕按下時廣播intent:  Java代碼   btnSend.setOnClickListener(new OnClickListener() {                         public void onClick(View v) {                   Intent intent = new Intent();                   intent.setAction("com.demo.appwidget.refresh");                   intent.putExtra("value", teInput.getText().toString());                   SendMsgActivity.this.sendBroadcast(intent);               }           });     在接收端:  Java代碼   if(intent.getAction().equals("com.demo.appwidget.refresh")) {               String value = intent.getStringExtra("value");                         RemoteViews appWidgetView = new RemoteViews(context.getPackageName(), R.layout.widget_layout_demo);               appWidgetView.setTextViewText(R.id.tv1, value);               appWidgetView.setTextViewText(R.id.tv2, value);               AppWidgetManager.getInstance(context).updateAppWidget(new ComponentName(context, AppWidgetDemo.class), appWidgetView);           }     判斷是否是感興趣的Action,是的話就取值,然後更新。  6.2.2接收系統消息刷新:  比如intent-filter中再增加一個action:"android.provider.Telephony.SMS_RECEIVED",在AndroidMenifest.xml中任意位置添加<uses-permission android:name="android.permission.RECEIVE_SMS" />設置好權限,當系統有短消息收到時就能觸發onReceive了。  但是有些Action比較特殊,比如android.intent.action.TIME_TICK,根據android.content.intent文檔中的描述:You can not receive this through components declared in manifests, only by exlicitly registering for it with Context.registerReceiver().  這個Action在AndroidManifest.xml中聲明了也沒用,必須要自己開個服務注冊receiver才能收到,然後再轉發一次給自己。    6.3直接在外部Activity或者Service中刷新:  Java代碼   btnRefresh.setOnClickListener(new OnClickListener() {                  public void onClick(View v) {           String value = teInput.getText().toString();           RemoteViews appWidgetView = new RemoteViews(SendMsgActivity.this.getPackageName(), R.layout.widget_layout_demo);           appWidgetView.setTextViewText(R.id.tv1, value);           appWidgetView.setTextViewText(R.id.tv2, value);           AppWidgetManager.getInstance(SendMsgActivity.this)               .updateAppWidget(new ComponentName(SendMsgActivity.this, AppWidgetDemo.class), appWidgetView);       }   });     此段代碼可直接刷新AppWidget的內容,不會觸發其onUpdate()。  7.響應點擊事件  因為onUpdate是每個AppWidget被放置到桌面上時都會被呼叫的函數,所以在此函數中完成事件的關聯:  Java代碼   Intent intent = new Intent(context, SendMsgActivity.class);   PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);   appWidgetView.setOnClickPendingIntent(R.id.tv1, pendingIntent);     另外要注意此段代碼必須要在appWidgetManager.updateAppWidget()之前,否則是不會生效的。  運行後可以點擊AppWidget的第一個控件,就能呼叫指定的Activity了。  8.Config Activity  這個可直接參考SDK文檔中的Dev Guide-->App Widgets了。 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved