- 最近把公司智能家具類的應(yīng)用中的一個負(fù)離子凈化顯示的控件重寫了脸狸,干脆就封裝了一下起個高大上的名字空氣凈化器控件最仑,感覺比負(fù)離子凈化牛逼一點,好像最近錘子也發(fā)布了一個空氣凈化器炊甲。
main.png
- 再來個動態(tài)的(Gif效果好差沒辦法它限制5M大小了泥彤,真實效果:扇葉是減速運(yùn)動的),還是看后面吧
mode.gif
- 一共才寫了幾個篇博客卿啡,沒經(jīng)驗啊吟吝,看了下別人的都寫原理什么的,這次就寫一下里面相當(dāng)比較復(fù)雜的效果的颈娜,其實剑逃,,官辽,蛹磺,沒什么復(fù)雜的,不知道從何說起撿幾個用的到的說同仆。
network1.gif
network1.gif
1. 實現(xiàn)的功能 (注意以思路為主)
- 1. 改變上中下字體大小萤捆,字體信息
- 2. 背景顏色實現(xiàn)漸變切換
- 3. 實現(xiàn)扇葉無縫開啟和關(guān)閉,從上次結(jié)束的位置開始動畫
- 4. 實現(xiàn)顆粒物效果
- 5. 無縫改變扇葉的速度
- 6.實現(xiàn)扇葉的漸變顯示,更加真實
2. 實現(xiàn)扇葉的漸變 (類似于真實扇葉的卷起來效果)
扇葉對比
pan1.png
pan2.png
- 簡單說下這個的實現(xiàn)鳖轰,其實實現(xiàn)虛線畫圓真心簡單兩行代碼解決。
// kotlin版 java也是一樣就是設(shè)置一下繪制效果就可以繪制虛線圓
val pathEffect = DashPathEffect(floatArrayOf(mPaint.strokeWidth*0.4f,mPaint.strokeWidth),0f)
mPaint.pathEffect = pathEffect
canvas.drawCircle(dashedRingCx,dashedRingCy,dashedRingRadius,mPaint)
-
但是 漸變的怎么繪制呢扶镀?上面的方法就不能用了蕴侣,因為Android繪制漸變的我想到的只有LinearGradient,我說的是一個個繪制漸變臭觉,先說下我的方法昆雀,LinearGradient需要傳入好幾個參數(shù)其中這里比較重要的就是x0,y0,x1,y1,就是你需要從那個點漸變到那個點蝠筑,直接再上個圖標(biāo)就是求出圖中兩個就可以繪制一個漸變的小圓環(huán)了狞膘,然后怎么繪制一個圓弧了。
pan11.png
// kotlin版 java也是一樣
//實現(xiàn)漸變扇葉
while (curAngle < 360 - mEachPanAngle) {
val x0 = measuredWidth/2f + (Math.cos((curAngle)*Math.PI/180)*(dashedRingRadius-dashedRadiusDiff*0.5)).toFloat()
val y0 = measuredHeight/2f + (Math.sin((curAngle)*Math.PI/180)*(dashedRingRadius-dashedRadiusDiff*0.5)).toFloat()
val x1 = measuredWidth/2f + (Math.cos((curAngle+mEachPanAngle)*Math.PI/180)*(dashedRingRadius+dashedRadiusDiff*0.5)).toFloat()
val y1 = measuredHeight/2f + (Math.sin((curAngle+mEachPanAngle)*Math.PI/180)*(dashedRingRadius+dashedRadiusDiff*0.5)).toFloat()
val shader = LinearGradient(x0, y0, x1, y1, Color.parseColor("#22ffffff"), Color.parseColor("#ffffffff"), Shader.TileMode.CLAMP)
mPaint.shader = shader
canvas?.drawArc(rectF, curAngle, mEachPanAngle, false, mPaint)
curAngle = curAngle + mEachPanAngle + mEachPanAngleGap
}
mPaint.shader = null //記得清除
3. 實現(xiàn)的漸變背景
這個的實現(xiàn)方法就很多了可以直接屬性動畫一個起始值一個結(jié)束值什乙,設(shè)置animator.setEvaluator(ArgbEvaluator())挽封,還有一個就是使用Hsv 使顏色漸變更適合人類觀感,公式就不寫臣镣,網(wǎng)上有源碼里也有辅愿。
4. 實現(xiàn)扇葉無縫開啟和關(guān)閉
這個動畫還是使用屬性動畫,但注意每次開啟和關(guān)閉時傳入的值忆某,當(dāng)前值為起始值点待,結(jié)束值為你要到的值,代碼其實很簡單。
airpurge.gif
private fun onFanAnim(isOpenFan: Boolean) {
if (mJumpAnimator != null && mJumpAnimator!!.isRunning) {
mJumpAnimator!!.cancel()
}
if (isOpenFan) {
mJumpAnimator = ObjectAnimator.ofFloat(this,"dashedRadiusDiff",dashedRadiusDiff,mDashedRingWidth)
mJumpAnimator!!.interpolator = DecelerateInterpolator()
mJumpAnimator!!.addListener(object : Animator.AnimatorListener{
override fun onAnimationRepeat(p0: Animator?) {
}
override fun onAnimationEnd(p0: Animator?) {
if (!isCancelJumpAnim) {
mPanListener?.onHasOpen()
onRotateAnim()
}
isCancelJumpAnim = false
}
override fun onAnimationCancel(p0: Animator?) {
isCancelJumpAnim = true
}
override fun onAnimationStart(p0: Animator?) {
}
})
mJumpAnimator!!.duration = 2000
} else {
mJumpAnimator = ObjectAnimator.ofFloat(this,"dashedRadiusDiff",dashedRadiusDiff,0f)
mJumpAnimator!!.interpolator = AccelerateInterpolator()
mJumpAnimator!!.addListener(object : Animator.AnimatorListener{
override fun onAnimationRepeat(p0: Animator?) {
}
override fun onAnimationEnd(p0: Animator?) {
if (dashedRadiusDiff == 0f) {
mPanListener?.onHasClose()
}
}
override fun onAnimationCancel(p0: Animator?) {
}
override fun onAnimationStart(p0: Animator?) {
}
})
mJumpAnimator!!.duration = 1200
}
mJumpAnimator!!.start()
}
5. 實現(xiàn)顆粒物效果
- 1.實現(xiàn)顆粒物無方向飄動
- 2.順時針向圓心運(yùn)動就是實現(xiàn)被設(shè)備吸入效果
granule.gif
這個實現(xiàn)方法非常多我實現(xiàn)方法應(yīng)該是比較簡單的弃舒,但效果不是特別符合空氣效果癞埠,顆粒物實現(xiàn)了兩個效果一個隨機(jī)流動還有一個隨著扇葉漸變到,1.無方向浮動是每次刷新都進(jìn)行加一個隨機(jī) -0.5 ~ 0.5數(shù)字 2.被設(shè)備吸入的效果使用角度增加聋呢,半徑減小是不是很簡單苗踪。
6. 無縫改變扇葉的速度 (GIF效果不太好)
changespeed.gif
這個實現(xiàn)過程更簡單了每次改變動畫的時間但要記住起點是上一次動畫結(jié)束點,終點是結(jié)束點+360
7 .必須人工解釋一下這個GIF效果實現(xiàn)是1.每個進(jìn)度端實現(xiàn)顏色的漸變 2.就是變速了坝冕,當(dāng)數(shù)字比較大的時候轉(zhuǎn)的快點徒探,隨著進(jìn)度減小慢慢減速,最后關(guān)閉設(shè)備效果喂窟,這個圖轉(zhuǎn)快了就和沒轉(zhuǎn)轉(zhuǎn)一樣测暗。
mode.gif