- 本文已授權微信公眾號: 鴻洋 (hongyangAndroid) 原創首發
最近把公司智慧傢俱類的應用中的一個負離子淨化顯示的控制元件重寫了,乾脆就封裝了一下起個高大上的名字空氣淨化器控制元件,感覺比負離子淨化牛逼一點,好像最近錘子也釋出了一個空氣淨化器。
再來個動態的(Gif效果好差沒辦法它限制5M大小了,真實效果:扇葉是減速運動的),還是看後面吧
一共才寫了幾個篇部落格,沒經驗啊,看了下別人的都寫原理什麼的,這次就寫一下里面相當比較複雜的效果的,其實,,,,沒什麼複雜的,不知道從何說起撿幾個用於的說。
1. 實現的功能 (注意以思路為主)
- 1. 改變上中下字型大小,字型資訊
- 2. 背景顏色實現漸變切換
- 3. 實現扇葉無縫開啟和關閉,從上次結束的位置開始動畫
- 4. 實現顆粒物效果
- 5. 無縫改變扇葉的速度
- 6.實現扇葉的漸變顯示,更加真實
2. 實現扇葉的漸變 (類似於真實扇葉的捲起來效果)
扇葉對比
- 簡單說下這個的實現,其實實現虛線畫圓真心簡單兩行程式碼解決。
// kotlin版 java也是一樣就是設定一下繪製效果就可以繪製虛線圓
val pathEffect = DashPathEffect(floatArrayOf(mPaint.strokeWidth*0.4f,mPaint.strokeWidth),0f)
mPaint.pathEffect = pathEffect
canvas.drawCircle(dashedRingCx,dashedRingCy,dashedRingRadius,mPaint)
複製程式碼
- 但是 漸變的怎麼繪製呢?上面的方法就不能用了,因為Android繪製漸變的我想到的只有LinearGradient,我說的是一個個繪製漸變,先說下我的方法,LinearGradient需要傳入好幾個引數其中這裡比較重要的就是x0,y0,x1,y1,就是你需要從那個點漸變到那個點,直接再上個圖示就是求出圖中兩個就可以繪製一個漸變的小圓環了,然後怎麼繪製一個圓弧了。
// kotlin版 java也是一樣
//實現漸變扇葉
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. 實現的漸變背景
這個的實現方法就很多了可以直接屬性動畫一個起始值一個結束值,設定animator.setEvaluator(ArgbEvaluator()),還有一個就是使用Hsv 使顏色漸變更適合人類觀感,公式就不寫,網上有原始碼裡也有。
4. 實現扇葉無縫開啟和關閉
這個動畫還是使用屬性動畫,但注意每次開啟和關閉時傳入的值,當前值為起始值,結束值為你要到的值,程式碼其實很簡單。
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. 實現顆粒物效果
這個實現方法非常多我實現方法應該是比較簡單的,但效果不是特別符合空氣效果,顆粒物實現了兩個效果一個隨機流動還有一個隨著扇葉漸變到,1.無方向浮動是每次重新整理都進行加一個隨機 -0.5 ~ 0.5數字 2.被裝置吸入的效果使用角度增加,半徑減小是不是很簡單。
- 1.實現顆粒物無方向飄動
- 2.順時針向圓心運動就是實現被裝置吸入效果
6. 無縫改變扇葉的速度 (GIF效果不太好)
這個實現過程更簡單了每次改變動畫的時間但要記住起點是上一次動畫結束點,終點是結束點+360