日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android覆盖扩散动画,[Android]多层波纹扩散动画——自定义View绘制

發布時間:2023/12/15 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android覆盖扩散动画,[Android]多层波纹扩散动画——自定义View绘制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

之前整理過一些屬性動畫的基本操作,這一段時間的動畫相關需求都安然度過了。直到這次……

一、另一種動畫需求

多數交互中的動畫都是讓單個頁面元素動起來,這種就很適合用屬性動畫實現。但是對于 多個元素、非頁面內元素 的動畫需求,就不方便用View+屬性動畫實現了。

舉個例子,也就是這次做的:

波紋效果需要同時繪制 多個 同心圓,而且這些圓 不是頁面內的元素,未觸發之前不需要顯示。如果用屬性動畫實現,至少需要在xml布局文件中添加多個ImageView畫圓,效率低還不易復用。

二、WaveView分析

使用自定義View繪制動畫的主要思路是這樣的:

分解動畫成幀,考慮如何在onDraw中繪制每一幀

提取出繪制所需參數,分為隨時間變化和不可變兩種,不可變參數可以暴露出去(setter方法/attribute設置)

總結隨時間變化的參數變化規律,實現時間軸

按需求提供出播放,暫停,停止,重置等等方法

按照這個思路,一步步實現一下WaveView吧。

第一步:

在onDraw中畫圓需要用到canvas.drawCircle方法,四個參數:圓心x、y坐標,半徑和Paint。WaveView繪制的每一幀都是圓,區別是圓的半徑,數量,透明度。還需要設置圓的最小半徑和最大半徑,以及擴散的時候兩個圓的半徑差。

每次繪制只需要把所有的圓畫出來:

第二步:

擴散過程中隨時間變化的參數只有半徑和透明度。圓的數量,最小最大半徑和半徑差則是不可變參數。所有的都加了默認值,防止

第三步:

最艱難的一步,時間軸。我們需要一個定時觸發的機制去改變mWaveList中的每一個值,還要同時修改paint的alpha值。這個變量嘛,還是越少越方便,波紋的效果是半徑越大alpha越小,只要控制半徑變化就可以計算出alpha。然后便是循環的問題,當波紋半徑大于最大半徑波紋就會消失,此時便可循環使用,再從最小半徑擴散一次。

我這里的時間軸用了CountDownTimer,應該不是一種很好的選擇,只是個人習慣寫起來順手了…

第四步:

最后這個就簡單了,直接控制CountDownTimer的start和cancel就可以了。

三、再完善一下?

內部功能已經實現了,還要提取參數的設置方法,方便其他地方使用呀。java中需要添加setter/getter方法,用模版代碼生成就好,kotlin的話直接把需要暴露的field改為public即可。

如果需要在xml布局文件中設置默認參數,還需要添加對應的attribute,現在這樣已經夠用了,我就不加了?

import android.content.Context

import android.graphics.Canvas

import android.graphics.Color

import android.graphics.Paint

import android.os.CountDownTimer

import android.util.AttributeSet

import android.view.View

class WaveView@JvmOverloads constructor(

context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0

) : View(context, attrs, defStyleAttr) {

private val paint:Paint = Paint()

public var mBgColor = Color.TRANSPARENT

public var mWaveColor = Color.WHITE

public var mRadiusMin = 0f

public var mRadiusMax = 1080f

public var mWaveInterval = 240f

//用每次擴散半徑增加的值作為速度參數

public var speed = 10f

private val mWaveList = ArrayList()

private val timeline = object:CountDownTimer(300000,16){

override fun onTick(millisUntilFinished: Long) {

// 每個時間間隔都把正在擴散的波紋半徑增加

for (i in 0 until mWaveList.size){

mWaveList[i] = mWaveList[i] + speed

if (mWaveList[i] < mRadiusMin + mWaveInterval){

break

}

}

//最外層波紋超過最大值時,重新把它添加到波紋隊列末尾

if (mWaveList[0] > mRadiusMax){

mWaveList[0] = mRadiusMin

val newList = transList(mWaveList)

mWaveList.clear()

mWaveList.addAll(newList)

}

invalidate()

}

override fun onFinish() {

//盡量保證手動調用waveStop,就不會執行到這里

reset()

}

}

init {

initWave(mWaveList)

paint.color = mWaveColor

}

override fun onDraw(canvas: Canvas?) {

super.onDraw(canvas)

canvas!!.drawColor(mBgColor)

val centerX = canvas.width.div(2).toFloat()

val centerY = canvas.height.div(2).toFloat()

for (i in 0 until mWaveList.size){

paint.alpha = calcAlpha(mWaveList[i])

canvas.drawCircle(centerX, centerY, mWaveList[i], paint)

}

}

fun wave(){

timeline.start()

}

fun stopWave(){

timeline.cancel()

}

fun reset(){

timeline.cancel()

mWaveList.clear()

initWave(mWaveList)

}

private fun initWave(waveList: ArrayList){

val waveNum = ((mRadiusMax-mRadiusMin)/mWaveInterval).toInt() + 2

for (i in 1..waveNum){

waveList.add(mRadiusMin)

}

}

private fun transList(list: ArrayList):ArrayList{

val newList = ArrayList()

(1 until list.size).mapTo(newList) { list[it] }

newList.add(list[0])

return newList

}

// 通過半徑計算透明度,趨勢是半徑越大越透明,直到看不見

private fun calcAlpha(r:Float):Int = ((mRadiusMax - r)/ mRadiusMax * 120).toInt()

}

復制代碼

最終得到的就是這樣的一個View啦,使用方法大概是這樣的:

在xml中放一個WaveView

findViewById之后,set基本參數

在需要的時機執行wave()方法

四、后記

做成這樣應該可以滿足設計師dalao們的需求了,呼~

自定義View是一個涵蓋內容很廣泛的課題,除了完全實現一個可展示、可交互的控件,還能優化布局的繪制效率,實現迷之交互,以及這特別的動畫效果,需要深入學習的內容還有很多呀。

近期在惡補Kotlin,打算進入實踐了,所以寫Demo的時候都用的Kotlin。但是目前的項目都是Java的,所以又翻譯了一版Java的。完整代碼見Github吧。

前往github

如有問題或是建議,歡迎留言評論。

總結

以上是生活随笔為你收集整理的android覆盖扩散动画,[Android]多层波纹扩散动画——自定义View绘制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。