以下是比較精簡的實作方法
設定動畫的監聽 (animation listener)
在上一篇是說,想要實作出 fade in 跟 fade out 的感覺,所以監聽 fade in 的結束,並且在結束的時候立馬接上 fade out。
因為寫了兩個動畫綁定,太冗長了。後來更正另一個作法,其實 fade out 就是 fade in 反過來做而已,所以實際上我只做了一個 fade in ,並且重複 (repeat) 它,在重複的時候把它換成 reverse,就會有這種效果出現了,如以下程式碼
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="2000"
android:repeatMode="reverse"
android:repeatCount = "1"
>
</alpha>
這樣,就直接省去了把兩個動畫使用很冗長的方法綁在一起,而只要寫一個 listener 就好了。
動畫的結尾樣子
這個動畫的結尾是 fade out,整個圖片會消失。但是並沒有如想像一般,當動畫全部結束之後,會回到該圖片預設狀態,也就是淡掉之後又整張再顯示出來。這時原先的處理方式就是直接設定為 INVISIBLE
,但後來發現另一個好的方法,就是把 fillAfter
設為 true
,那麼就會把動畫的最後一幕套用在該圖上面,也就是說,如果最後一幕是全部淡掉的,那麼就直接套用進去該圖,而不是使用他預設的值,參考連結
android:fillAfter = "true"
動畫音效
這邊我使用了兩種方法實作出來,一種是 MediaPlayer.create
,另一種是 SoundPool
。兩種方法大同小異,使用 MediaPlayer.create
比較單純,單純放一首歌,放一小段預設好的音效,而 SoundPool
則是一個能夠裝很多音效的方法。這邊先設定音效是無限循環,當動畫結束之後就去停止他。
MediaPlayer
mp = MediaPlayer.create(this, R.raw.star)
mp?.isLooping = true
mp?.setOnPreparedListener {
Log.d("", "music is prepared")
mp?.start()
setStartAnim()
}
SoundPool
private var sp = SoundPool.Builder().setMaxStreams(8).build();
private val sounds = mutableListOf<Int>()
sounds.add(sp.load(this, R.raw.star, 1))
sp.setOnLoadCompleteListener { soundPool, sampleId, status ->
soundPool.play(sounds[0], 1.0f, 1.0f, 1, -1, 1.0f)
setStartAnim()
}
為何音效出不來呢?
自己在 onCreate()
的動畫時,已經寫下了以下 code,為何沒有任何聲音出現呢?
soundPool.play(sounds[0], 1.0f, 1.0f, 1, -1, 1.0f)
原來在載入音效的時候,因為載入很需要時間,所以會以 非同步 (asynchronous) 的方式去做載入。意思就是說,在做載入聲音的這個麻煩事情,主程式會生出另一個 thread,姑且把它當作小僕人好了,這個小僕人像是我的幫手,他去把音樂載進來,而我的主程式並不會等音樂載入,會直接繼續去做其他事情。
這時候你就會發現,主程式會直接去做動畫,這時候,因為小僕人還沒有把音效弄好,所以自然而然不會有音樂!該怎辦呢?那就是主程式等著小僕人把音樂都準備好了,之後再去跑動畫,程式碼就該改成下面的樣子
sp.setOnLoadCompleteListener { soundPool, sampleId, status ->
soundPool.play(sounds[0], 1.0f, 1.0f, 1, -1, 1.0f)
setStartAnim()
}
當音樂確定完成載入,才會去執行裡面的 play
以及啟動動畫的部分唷!