iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
0
Mobile Development

Android 音樂播放器自己來系列 第 20

播放介面實作(6) - Widget 基礎

  • 分享至 

  • xImage
  •  

在前幾天的章節加入了 NowPlaying 頁面,來顯示歌曲資訊和提供控制播放的行為。今天要來加入另一個元件 - Widget,Widget 是自定義在桌面上的元件,在桌面上就可以控制 App 或是瀏覽 App 的資訊,舉例來說:載具條碼、天氣、時鐘,能在桌面就顯示,就不用點開 App 才能獲取資訊。在 iOS 14 也加入了 Widget 元件,代表這是一個趨勢,讓使用者能更方便的操作 App。

音樂播放器在 Widget 上的顯示和操作,也類似 NowPlaying 頁面,但 Widget 屬於 Android 提供的元件,不是單純的 UI layout,就先來看一下 Widget 的實作和基本設定吧。

Android Studio 有提供 Widget 樣板的設定,可以從 New / Widget 開啟設定的頁面,就跳出了設定頁面,可以設定 Widget 名稱,放的位置,是否可以放大、縮小等...,這邊可以先選一下,之後還是可以透過程式碼來修改,這邊會產生一套 Widget 的樣板 code,包含 layout 和 config,點下確認後,會產生相對應的程式碼。
https://ithelp.ithome.com.tw/upload/images/20200920/20129728kS3chzQmLM.png

在 AndroidManifest 可以看到會註冊 receiver,可以得知這個元件本身是四大元件中的 BroadcastReceiver,透過收事件來更新 Widget 上的狀態。

intent-filter 內註冊 APPWIDGET_UPDATE,在 Widget 的選單上才會有出現 App 的 Widget,然後可以收到關於 Widget 的更新資訊,調整大小、是否加入或是移除了。

<receiver android:name=".MusicAppWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/music_app_widget_info" />
 </receiver>

meta-data 又是設定什麼呢,就是一開始在上面 Android Studio 上面設定的項目,可以設定大小,不過是用幾個 cell 來決定。初始寬度設定 4 個 cell,高度設定 1 個 cell,比較符合音樂播放器的樣式是(類似 Day 16 NowPlaying 小條 UI),還有設定在選單的顯示圖片,並設定可以長寬自由調整大小。

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

在 AndroidManifest 註冊了 MusicAppWidget,在程式碼這邊繼承 AppWidgetProvider,去實作更新的功能,相關的 Widget 邏輯都寫在這邊。

class MusicAppWidget : AppWidgetProvider() {
    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        // There may be multiple widgets active, so update all of them
        for (appWidgetId in appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId)
        }
    }

    override fun onEnabled(context: Context) {
        // Enter relevant functionality for when the first widget is created
        Log.d(TAG,"onEnabled")
    }

    override fun onDisabled(context: Context) {
        // Enter relevant functionality for when the last widget is disabled
        Log.d(TAG,"onDisabled")
    }

}

在 UI 更新時,使用 RemoteViews 的方式來更新,這個元件可以在其他的 Process,非 App 的 Process,然後可以透過這個方式來更新 UI,文件裡面有介紹支援的 UI 元件(ex: FrameLayout, RelativeLayout...),裡面沒有 ConstraintLayout,就不能用這個方式來畫 UI 了 XD

internal fun updateAppWidget(
    context: Context,
    appWidgetManager: AppWidgetManager,
    appWidgetId: Int
) {
    val widgetText = context.getString(R.string.appwidget_text)
    // Construct the RemoteViews object
    val views = RemoteViews(context.packageName, R.layout.music_app_widget)
    views.setTextViewText(R.id.appwidget_text, widgetText)

    // Instruct the widget manager to update the widget
    appWidgetManager.updateAppWidget(appWidgetId, views)
}

成果圖:

  • 選單:
    https://ithelp.ithome.com.tw/upload/images/20200920/20129728OZNnRxJJmj.png

  • 放在桌面上
    https://ithelp.ithome.com.tw/upload/images/20200920/20129728WCOXRTt1LD.png

明天就會來實作 Widget 的介面,顯示播放的資訊!

程式碼在這,分支名稱(day20_initial_widget_ui): Fancy/day20_initial_widget_ui


上一篇
播放介面實作(5) - NowPlaying 蓋板UI (抽色)
下一篇
播放介面實作(6) - Widget 頁面(顯示資訊)
系列文
Android 音樂播放器自己來30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言