Android- Widget (應(yīng)用微件/小組件/插件) 使用介紹

一寻仗、概念:

App Widget 即叫 應(yīng)用微件 或者 小組件/插件.
是可以嵌入其他應(yīng)用(如主屏幕)并 接收定期更新微型應(yīng)用視圖
這些視圖稱為界面中的微件.
例如,添加到桌面上的音樂Widget:

app_widget_music_sample.PNG

能夠容納其他應(yīng)用微件的應(yīng)用組件稱為 AppWidgetHost (應(yīng)用微件托管應(yīng)用)缤沦。
App 通過傳遞要顯示布局id 給RemoteViews, 即可以獲取Widget的實(shí)例對象.

官網(wǎng)介紹:
指南:https://developer.android.com/guide/topics/appwidgets
UI指南(更詳細(xì)): https://developer.android.com/develop/ui/views/appwidgets/overview

二、基礎(chǔ)知識

官網(wǎng)上的介紹順序有點(diǎn)難懂半醉,可以參考一下順序疚俱,方便理解.

要創(chuàng)建App Widget,大體需要以下三點(diǎn):

(1) 視圖布局
定義 Widget的布局 (xml)

注意:
這個布局需要添加到 RemoteViews缩多, 而 RemoteViews 是不支持 ConstraintLayout的.
支持:LinearLayout/FrameLayout/RelativeLayout/GridLayout, 以及TextView/Button等基礎(chǔ)控件(不支持他們的子類)

(2) AppWidgetProviderInfo 對象
將數(shù)據(jù)封裝在元素<appwidget-provider>里
描述App Widget的元數(shù)據(jù)(meta-data)呆奕,如布局、更新頻率和 AppWidgetProvider 類衬吆。
此對象應(yīng)在 XML 中定義 并且 要在 AndroidManifest.xml中聲明梁钾。

(3) AppWidgetProvider 類實(shí)現(xiàn)
定義了 基于廣播事件, 通知到 Widget 的方法。
會在更新逊抡、啟用姆泻、停用和刪除 Widget 時收到廣播零酪。
要在 AndroidManifest.xml中聲明
App可以通過它操作RemoteViews拇勃,例如更新等

三四苇、使用流程

1. 創(chuàng)建Widget 內(nèi)容的 布局

/layout/widget_content.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/forward_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="這是一個測試的Widget內(nèi)容 點(diǎn)擊我快速使用 App 某個功能" />

</RelativeLayout>

2. 添加 AppWidgetProviderInfo 元數(shù)據(jù)

數(shù)據(jù)封裝在元素<appwidget-provider>里.
/xml/example_appwidget_info.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialKeyguardLayout="@layout/widget_content"
    android:initialLayout="@layout/widget_content"
    android:minHeight="110dp"
    android:minWidth="180dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="0"
    android:widgetCategory="home_screen">

</appwidget-provider>

其中,
(1) initialLayout 則表示 widget 顯示的內(nèi)容
(2) minWidth / minHeight 表示W(wǎng)idget默認(rèn)情況下方咆,占用的最小空間. (最小大小不得超過 4 x 4 單元格)
(3) previewImage 表示預(yù)覽圖片月腋,即用戶添加時展示的 (這里是example_appwidget_preview.png )
(4) resizeMode 指定可以按什么規(guī)則來調(diào)整大小 (“horizontal”、“vertical”和“none”)
(5) widgetCategory 是否可以顯示在主屏幕(home_screen) 和/或鎖定屏幕 (keyguard)
注:這個XML 文件將會在AndroidManifest 聲明 AppWidgetProvider組件時瓣赂,由meta-data引用

3. 使用 AppWidgetProvider 類

AppWidgetProvider 類擴(kuò)展了 BroadcastReceiver, 作為一個輔助類來處理應(yīng)用微件廣播榆骚。
僅接收與Widget有關(guān)的事件廣播,例如當(dāng)更新煌集、刪除妓肢、啟用和停用Widget時發(fā)出的廣播.

當(dāng)發(fā)生這些廣播事件時,AppWidgetProvider 會接收以下方法調(diào)用:
onUpdate()
onAppWidgetOptionsChanged()
onDeleted(Context, int[])
onEnabled(Context)
onDisabled(Context)
onReceive(Context, Intent)

最重要的是 onUpdate苫纤, 如果要處理任何用戶交互事件碉钠,都需要在此回調(diào)處理.
這里我們設(shè)置,點(diǎn)擊了Widget 后卷拘,跳轉(zhuǎn)到 ExampleActivity 里.

class ExampleAppWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each App Widget that belongs to this provider
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity
            val pendingIntent: PendingIntent = Intent(context, ExampleActivity::class.java)
                .let { intent ->
                    PendingIntent.getActivity(context, 0, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) // set flags to fix fatal when sdk >=31
                }

            // Get the layout for the App Widget and attach an on-click listener
            // to the button
            val views: RemoteViews = RemoteViews(
                context.packageName,
                R.layout.widget_content
            ).apply {
                setOnClickPendingIntent(R.id.forward_button, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current app widget
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}
    

其中放钦,
(1) appWidgetIds 是一個ID 數(shù)組,對應(yīng)每一添加到主屏幕的Widget實(shí)例.
(即:可以在主屏幕添加 多個Widget)
(2) 不同的Widget 實(shí)例恭金,updatePeriodMillis 更新周期表依照第一個Widget實(shí)例.
(3) pendingIntent 用于點(diǎn)擊Widget上的Button時,跳轉(zhuǎn)到ExampleActivity
注意:在SDK>=31 上褂策,需要設(shè)置 FLAG_IMMUTABLE. 否則會出現(xiàn)fatal error:Strongly consider using FLAG_IMMUTABLE...
(4) ExampleActivity 是一個簡單的Activity,
代碼:

class ExampleActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_example)
    }
}

activity_example 為布局資源横腿,僅顯示一個TextView

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ExampleActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show this From Widget!!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

4. 在AndroidManifest中聲明 AppWidgetProvider 并聲明 AppWidgetProviderInfo

        <receiver android:name="ExampleAppWidgetProvider"
            android:exported="true">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/example_appwidget_info" />
        </receiver>

需要在清單中聲明后,才能在小組件設(shè)置里添加.

此處的聲明可以反推出來:
(1) App Widget的入口斤寂,其實(shí)依賴 <intent-filter>里聲明的action:android.appwidget.action.APPWIDGET_UPDATE
(2)猜測系統(tǒng)(Launcher) 將會遍歷所有的AndroidManifest, 然后找到有這個action所在的組件.
在用戶長按應(yīng)用圖標(biāo)時耿焊,可顯示應(yīng)用 自定義的組件。
(3)而這個自定義組件的內(nèi)容是 從 meta-data里的 "android.appwidget.provider" 讀取出來遍搞。
(4)后續(xù)罗侯,有小組件的事件,則是通知到它所聲明的receiver (這里是ExampleAppWidgetProvider)

至此溪猿,已經(jīng)完成所有钩杰,
運(yùn)行app即可體驗(yàn).

5. 效果圖如下:

(1)添加Widget


demo_add widget.PNG

(2) 添加Widget時的 預(yù)覽圖


add widget preview.PNG

(3) Widget 顯示圖


widget_in home screen.PNG

(4) 點(diǎn)擊Widget的button 后則會跳轉(zhuǎn)的對應(yīng)的Activity

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诊县,隨后出現(xiàn)的幾起案子讲弄,更是在濱河造成了極大的恐慌,老刑警劉巖依痊,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件避除,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瓶摆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門凉逛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人群井,你說我怎么就攤上這事状飞。” “怎么了蝌借?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵昔瞧,是天一觀的道長。 經(jīng)常有香客問我菩佑,道長自晰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任稍坯,我火速辦了婚禮酬荞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞧哟。我一直安慰自己混巧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布勤揩。 她就那樣靜靜地躺著咧党,像睡著了一般。 火紅的嫁衣襯著肌膚如雪陨亡。 梳的紋絲不亂的頭發(fā)上傍衡,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機(jī)與錄音负蠕,去河邊找鬼蛙埂。 笑死,一個胖子當(dāng)著我的面吹牛遮糖,可吹牛的內(nèi)容都是我干的绣的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼欲账,長吁一口氣:“原來是場噩夢啊……” “哼屡江!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起敬惦,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盼理,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后俄删,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宏怔,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奏路,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了臊诊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸽粉。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖抓艳,靈堂內(nèi)的尸體忽然破棺而出触机,到底是詐尸還是另有隱情,我是刑警寧澤玷或,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布儡首,位于F島的核電站,受9級特大地震影響偏友,放射性物質(zhì)發(fā)生泄漏蔬胯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一位他、第九天 我趴在偏房一處隱蔽的房頂上張望氛濒。 院中可真熱鬧,春花似錦鹅髓、人聲如沸舞竿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽骗奖。三九已至,卻和暖如春醒串,著一層夾襖步出監(jiān)牢的瞬間重归,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工厦凤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人育苟。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缘揪。 傳聞我的和親對象是個殘疾皇子证逻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容