Android UI組件AppWidget控制項入門詳解_Android

來源:互聯網
上載者:User

Widget引入 

我們可以把Widget理解成放置在案頭上的小工具(掛件),有了Widget,我們可以很方便地直接在案頭上進行各種操作,例如播放音樂。 

當我們長按案頭時,可以看到Widget選項,如下圖所示: 


點擊上圖中箭頭處的widgets表徵圖,會出現如下介面:(都是widget) 

長按上圖中的任意一個widget,就可以將其放到案頭上。 

Widget的使用
Widget的實現思路 
(1)在AndroidManifest中聲明AppWidget; 
(2)在xml目錄中定義AppWidget的設定檔; 
(3)在layout目錄中定義Widget的布局檔案; 
(4)建立一個類,繼承AppWidgetProvider類,實現具體的widget商務邏輯。 

我們需要建立一個類,繼承AppWidgetProvider。點開AppWidgetProvider,發現AppWidgetProvider竟然是繼承自BroadcastReceiver。 

為什麼Widget是一個廣播接收器呢?我們知道,BroadcastReceiver類中有一個onReceive方法,用來接收廣播。當我們在案頭掛件上去做操作時,必然引起應用的改變,這就涉及到掛件和應用之間的通訊,此時用廣播來通訊是再好不過了。 

Widget的具體使用步驟 

(1)建立一個類TestWidget.java,繼承AppWidgetProvider:
 TestWidget.java: 

import android.appwidget.AppWidgetProvider;import android.content.Context;import android.content.Intent;/** * Created by smyhvae on 2016/9/7. */public class TestWidget extends AppWidgetProvider{ @Override public void onReceive(Context context, Intent intent) {  super.onReceive(context, intent); }} 

(2)因為Widget是一個廣播接收器,所以我們需要在資訊清單檔中註冊:

 <!-- 聲明widget對應的AppWidgetProvider -->  <receiver android:name=".TestWidget">   <intent-filter>    <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>   </intent-filter>   <meta-data    android:name="android.appwidget.provider"    android:resource="@layout/widget_setting"/>  </receiver> 

04行:action是過濾條件,用來過濾行為,監測widget的更新。
08行:android:resource指定了widget的配置。我們知道,屬性在資訊清單檔中是用來儲存資料的。 

(3)layout檔案夾中建立檔案widget_setting.xml:(widget的設定檔)
 setting_widget.xml: 

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:initialLayout="@layout/layout_widget"     android:minHeight="140dp"     android:minWidth="140dp"     android:previewImage="@mipmap/ic_launcher"     android:updatePeriodMillis="20000"     android:widgetCategory="home_screen" ></appwidget-provider> 

08行: android:initialLayout 指定了widget的布局。
09行:android:updatePeriodMillis 指定更新的時間周期
10行: android:widgetCategory="home_screen" 將widget顯示在主畫面上(也可以顯示在鎖屏上)

(4)layout檔案夾中建立檔案layout_widget.xml:(widget的布局)
 layout_widget.xml: 

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"> <TextView  android:id="@+id/textView"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_gravity="center_horizontal"  android:text="Large Text"  android:textAppearance="?android:attr/textAppearanceLarge"/> <Button  android:id="@+id/button2"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_gravity="center_horizontal"  android:text="New Button"/></LinearLayout> 

到此,程式就可以跑起來了。運行程式之後,長按案頭,點開"Widget"按鈕,可以看到我們剛剛設計出的widget: 


長按上圖中的箭頭處,就可以將我們設計出的widget拖放到案頭上了: 


Widget的點擊和更新【重要】 

我們知道,TestWidget.java繼承自AppWidgetProvider,而AppWidgetProvider在繼承BroadcastReceiver之後,重寫onReceive方法,然後還自訂了很多方法: 


上圖中,包含了被刪除時、被禁用時、被啟用時、被更新時等各種方法。尤其重要的是onReceive()方法和onUpDate()方法。
 當小組件被改變時(比如被安裝到案頭),系統會發送一個更新的廣播(上圖紅框部分所示)。我們在setting_widget.xml中設定了widget的更新頻率,這個也會調用更新。 

有人可能會問,我開機之後,天氣等widget為何不更新了?這是因為進程被殺死了,那我們只能把這個控制項先移除,然後再裝上,此時應用會發update更新的廣播。 

當需要做widget的點擊和更新時,我們需要在需要重寫onUpdate()方法,用來發送廣播。當程式初始化的時候,系統就會調用onUpdate()方法。 

onUpdate()方法中的代碼如下:

  @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {  super.onUpdate(context, appWidgetManager, appWidgetIds);  RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//需要構造一個RemoteViews  Intent intent = new Intent();  intent.setClass(context, TestWidget.class); //通過intent把廣播發給TestWidget本身,TestWidget接受到廣播之後,會調用。。進而重新整理借鑒  // 。  intent.setAction(WIDGET_BTN_ACTION);  PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);  remoteViews.setOnClickPendingIntent(R.id.widget_btn, pendingIntent);//控制項btn_widget的點擊事件:點擊按鈕時,會發一個帶action的廣播。  appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); //點擊完了之後,記得更新一下。 } 

代碼解釋:
首先需要new一個RemoteViews,構造方法裡需要傳遞兩個參數,一個是包名(context.getPacakgeName),一個是布局檔案(layout_widget)。
 然後通過remoteViews.setOnClickPendingIntent()設定按鈕的點擊事件。setOnClickPendingIntent()中需要傳遞兩個參數:一個是id(比如需要被點擊的button),一個是PendingIntent。PendingIntent是未來的意圖。
 於是我們需要事先構造一個PendingIntent,這個需要通過 PendingIntent.getBroadcast()來構造。getBroadcast()方法中需要傳遞四個參數,其中有一個是Intent。
 於是我們需要構造一個Intent。在intent裡發送廣播,並設定Action。
 按鈕點擊完了之後,記得調用appWidgetManager.updateAppWidget(int[] appWidgetIds, RemoteViews views)方法更新一下,第一個參數就是onUpdate方法中的參數,代表的是所有的控制項。 

在onUpdate()方法中通過intent發送按鈕點擊時間的廣播之後,我們需要在onReceive()方法中進行廣播的接收。
 onReceive()方法中的代碼如下: 

 @Override public void onReceive(Context context, Intent intent) {  super.onReceive(context, intent);  if (intent != null && TextUtils.equals(intent.getAction(), WIDGET_BTN_ACTION)) { //當intent不為空白,且action匹配成功時,就接收廣播,然後點擊事件成功   Log.i(WIDGET_BTN_ACTION, "is clicked");   //接下來開始做點擊事件裡面的內容   RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】構造一個RemoteViews   remoteViews.setTextViewText(R.id.widget_tv, "be clicked");   remoteViews.setTextColor(R.id.widget_tv, Color.RED);   AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 單例模式   ComponentName componentName = new ComponentName(context, TestWidget.class);   appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之後,記得更新一下  } } 

代碼解釋:
 當intent的action匹配成功時,開始執行做點擊時間之後的setText,不過這裡需要重新new 一個 RemoteViews,而不能共用onUpdate()方法中的RemoteViews(這是一個很大的坑)。
 執行完點擊事件之後的setText之後,記得調用appWidgetManager.updateAppWidget(ComponentName, RemoteViews)方法,第一個參數為組件名,需要我們自己new一下,第二個參數很好解釋。 

綜合來說,TestWidget.java的完整版代碼如下:
Testwidget.java:

 import android.app.PendingIntent;import android.appwidget.AppWidgetManager;import android.appwidget.AppWidgetProvider;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.graphics.Color;import android.text.TextUtils;import android.util.Log;import android.widget.RemoteViews;/** * Created by smyhvae on 2016/9/7. */public class TestWidget extends AppWidgetProvider { public static final String WIDGET_BTN_ACTION = "widget_btn_action"; @Override public void onReceive(Context context, Intent intent) {  super.onReceive(context, intent);  if (intent != null && TextUtils.equals(intent.getAction(), WIDGET_BTN_ACTION)) { //當intent不為空白,且action匹配成功時,就接收廣播,然後點擊事件成功   Log.i(WIDGET_BTN_ACTION, "is clicked");   //接下來開始做點擊事件裡面的內容   RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】構造一個RemoteViews   remoteViews.setTextViewText(R.id.widget_tv, "be clicked");   remoteViews.setTextColor(R.id.widget_tv, Color.RED);   AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 單例模式   ComponentName componentName = new ComponentName(context, TestWidget.class);   appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之後,記得更新一下  } } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {  super.onUpdate(context, appWidgetManager, appWidgetIds);  RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//需要構造一個RemoteViews  Intent intent = new Intent();  intent.setClass(context, TestWidget.class); //通過intent把廣播發給TestWidget本身,TestWidget接受到廣播之後,會調用。。進而重新整理借鑒  // 。  intent.setAction(WIDGET_BTN_ACTION);  PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);  remoteViews.setOnClickPendingIntent(R.id.widget_btn, pendingIntent);//控制項btn_widget的點擊事件:點擊按鈕時,會發一個帶action的廣播。  appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); //點擊完了之後,記得更新一下。 }} 

運行之後,把widget拖到案頭上,效果如下:

 

點擊按鈕後,效果如下:

 

工程檔案:(Android Studio 2.1) 

當然,widget還有很多其他的用途。比如:
 •與Service進行通訊
 •widget控制項的互動方法。
 •如何做一個案頭播放器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.