編輯:關於Android編程
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
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
第一,這貨速度太快,第二,模仿真機環境,第三,秒殺任何Android模擬器包括真機,不多說上圖,我忒忙! 官網:http://www.genymotion.com/鏡像圖
前言在日常開發APP 的過程中,隨著業務的擴展,規模的變化。我們的代碼規模也會逐漸變得龐大,每一個類裡的代碼也會逐漸增多。尤其是Activity和Fragment ,由於
MediaRecorder/MediaPlayer在Android手機上面,音頻的處理比視頻還要復雜,這真是出人意料。在前面的博文《Android開發筆記(五十七)錄像錄
最近用上了印象筆記,覺得android 版的底部導航欄挺不錯的,好多應用裡面都有用到,想著自己動手實現一下,不多說,先上圖: 要完成這樣的效果。需要自定義ViewGrou