1 Star 0 Fork 0

xiaow / AndroidPractiseCode

Create your Gitee Account
Explore and code with more than 8 million developers,Free private repositories !:)
Sign up
Clone or Download
SplashView.kt 5.60 KB
Copy Edit Web IDE Raw Blame History
xiaowu authored 2021-01-07 16:39 . add animator framework.
package com.github.jxiaow.animation
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.renderscript.Sampler
import android.util.AttributeSet
import android.view.View
import android.view.animation.LinearInterpolator
import android.view.animation.OvershootInterpolator
import androidx.core.animation.addListener
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
/**
* 采用策略模式分状态处理
* RotateState(旋转动画,在一个大圆上分布着许多小圆) :
* 1. 画背景 2. 画n个圆 3.动画改变圆的旋转角度
* MergingState(大圆的半径不断的变大,变小)
* ExpandState 水波纹扩散动画
*/
class SplashView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private var _state: SplashState? = null
private val currentState: SplashState
get() = _state ?: RotateState().also { _state = it }
// n个小圆画笔
private val colorCirclePaint = Paint().apply {
isAntiAlias = true
style = Paint.Style.FILL_AND_STROKE
}
// 圆的色彩集合
private val circleColors = resources.getIntArray(R.array.splash_circle_colors)
// 色彩圆的半径
private val colorCircleRadius = 19f
// 色彩圆旋转的角度
private var currentCircleRotateAngle = 0f
private val splashBgColor = Color.WHITE
// 色彩圆 大圆环的半径
private var circleRadius = 90f
private var currentRotateRadius = circleRadius
// 中心点坐标
private var centerX = 0f
private var centerY = 0f
private var dialDist = 0f
private var holeRadius = 0f
private val bgPaint = Paint().apply {
isAntiAlias = true
color = splashBgColor
style = Paint.Style.STROKE
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
centerX = w / 2f
centerY = h / 2f
dialDist = (sqrt(((w * w + h * h).toDouble())) / 2).toFloat()
}
override fun draw(canvas: Canvas) {
super.draw(canvas)
currentState.drawState(canvas)
}
abstract class SplashState {
abstract val animator: ValueAnimator?
abstract fun drawState(canvas: Canvas)
fun cancel() {
animator?.cancel()
}
}
private inner class ExpandState : SplashState() {
override val animator: ValueAnimator?
get() = ValueAnimator.ofFloat(colorCircleRadius, dialDist)
.apply {
duration = 2000L
addUpdateListener {
holeRadius = it.animatedValue as Float
postInvalidate()
}
}
init {
animator?.start()
}
override fun drawState(canvas: Canvas) {
drawBackground(canvas)
}
}
private inner class MergingState : SplashState() {
override val animator: ValueAnimator?
get() = ValueAnimator.ofFloat(0f, circleRadius)
.apply {
duration = 2000L
// 从最后一个值往回弹
interpolator = OvershootInterpolator()
addUpdateListener {
currentRotateRadius = it.animatedValue as Float
postInvalidate()
}
addListener(onEnd = {
_state = ExpandState()
})
}
init {
animator?.reverse()
}
override fun drawState(canvas: Canvas) {
drawBackground(canvas)
drawCircles(canvas)
}
}
private inner class RotateState : SplashState() {
override val animator: ValueAnimator?
get() = ValueAnimator.ofFloat(0f, (PI * 2).toFloat())
.apply {
interpolator = LinearInterpolator()
repeatCount = ValueAnimator.INFINITE
duration = 1000L
addUpdateListener {
currentCircleRotateAngle = it.animatedValue as Float
postInvalidate()
}
}
init {
animator?.start()
}
override fun drawState(canvas: Canvas) {
drawBackground(canvas)
drawCircles(canvas)
}
}
private fun drawCircles(canvas: Canvas) {
val circleAngle = PI * 2 / circleColors.size
for (i in circleColors.indices) {
val angle = i * circleAngle + currentCircleRotateAngle
val cx = centerX + cos(angle) * currentRotateRadius
val cy = centerY + sin(angle) * currentRotateRadius
colorCirclePaint.color = circleColors[i]
canvas.drawCircle(cx.toFloat(), cy.toFloat(), colorCircleRadius, colorCirclePaint)
}
}
private fun drawBackground(canvas: Canvas) {
if (holeRadius <= 0) {
canvas.drawColor(splashBgColor)
} else {
val strokeWidth = dialDist - holeRadius
val radius = holeRadius + strokeWidth / 2
bgPaint.strokeWidth = strokeWidth
canvas.drawCircle(centerX, centerY, radius, bgPaint)
}
}
fun splashDisappear() {
if (_state != null && _state is RotateState) {
_state?.cancel()
post { _state = MergingState() }
}
}
}

Comment ( 0 )

Sign in to post a comment

Android
1
https://gitee.com/jxiaow/practiseCodeAndroid.git
git@gitee.com:jxiaow/practiseCodeAndroid.git
jxiaow
practiseCodeAndroid
AndroidPractiseCode
master

Search