在 NowPlaying 小條 UI 上,要顯示 Play / Pause,就可以控制歌曲的播放和暫停,在前面的天數有提到,還會使用向量圖,在這邊就要再來使用啦,向量圖好處可以降低圖片大小,因為是向量圖,裡面就是描述,不會因為圖比較大張,檔案就比較大。還有另外一個好處是在圖片間的切換可以做動畫,細節可以參考之前的鐵人 30 天教學:Day23 VectorDrawable Animation 範例:play-pause,有介紹了實作了 Play / Pause 的教學。這邊(An Introduction to Icon Animation Techniques)還有介紹其他的向量動畫(ex: 下載、指紋辨識),還蠻有趣的。
Ref: https://ithelp.ithome.com.tw/articles/10208320
加入 Play / Pause 的按鈕,細部還有很多相關的向量圖相關的檔案,可以參考上面的教學。
<ImageButton
android:id="@+id/playPauseImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginEnd="15dp"
android:background="@android:color/transparent"
android:src="@drawable/asl_playpause"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription"
tools:src="@tools:sample/us_phones" />
在 NowPlayingViewModel 內加入 mediaButtonRes,依據播放狀態來更新要顯示 Play 或是 Pause
val mediaButtonRes = MutableLiveData<IntArray>()
mediaButtonRes.postValue(
when (playbackState.isPlaying) {
true -> intArrayOf(-R.attr.state_play, R.attr.state_pause) //Set pause
else -> intArrayOf(R.attr.state_play, -R.attr.state_pause) //Set play
}
)
在 NowPlayingFragment 內觀察 mediaButtonRes,然後 Play / Pause 按鈕本身也註冊 ClickListener,這樣使用者就可播放或是暫停這首歌,值得注意的是,這邊使用的是 songListViewModel 來執行播放功能,因為在 songListViewModel 已經有這個播放功能了,因此在 NowPlayingFragment 就使用了兩個 ViewModel (SongListViewModel 和 NowPlayingViewModel),因為 MVVM 不像 MVP 的view 和 presenter 之間是用綁定的,只能一對一,透過了觀察者的模式,有需要再去觀察,本身不需要綁定的關係,用起來更加方便了。
nowPlayingViewModel.mediaButtonRes.observe(viewLifecycleOwner,
Observer {
playPauseImage.setImageState(it, true)
})
playPauseImage.setOnClickListener {
nowPlayingViewModel.mediaMetadata.value?.let { songListViewModel.playMediaId(it.id)}
}
成果圖:
程式碼在這,分支名稱(day17_play_pause_button): Fancy/day17_play_pause_button