import android.os.Bundle
import android.view.animation.*
import android.widget.ImageView
import android.widget.RadioGroup
import android.widget.Switch
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var ivRotating: ImageView
private lateinit var switchRotate: Switch
private lateinit var rgGear: RadioGroup
private var currentGear = 1 // 当前档位(默认1挡)
private var previousGear = 1 // 上一个档位(用于判断过渡方向)
private var isRotating = false // 是否旋转中
private var currentRotationAngle = 0f // 当前旋转角度(衔接用)
private var rotationAnimationSet: AnimationSet? = null // 动画集
// 固定参数
private val TRANSITION_DURATION = 500L // 过渡时间(500ms)
private val ROTATE_ANGLE_TRANSITION = 60f // 过渡动画旋转角度(平缓适配)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rotation)
initView()
initListener()
}
private fun initView() {
ivRotating = findViewById(R.id.iv_rotating)
switchRotate = findViewById(R.id.switch_rotate)
rgGear = findViewById(R.id.rg_gear)
}
private fun initListener() {
// 档位切换监听(核心:记录上一档位,判断过渡方向)
rgGear.setOnCheckedChangeListener { _, checkedId ->
previousGear = currentGear // 先保存上一档位
currentGear = when (checkedId) {
R.id.rb_gear1 -> 1
R.id.rb_gear2 -> 2
R.id.rb_gear3 -> 3
else -> 1
}
if (isRotating) {
restartRotationWithDirection() // 按方向启动过渡动画
}
}
// 启停开关监听
switchRotate.setOnCheckedChangeListener { _, isChecked ->
isRotating = isChecked
if (isChecked) {
// 首次启动:默认加速过渡(从静止到当前档位)
startRotationWithTransition(accelerate = true)
} else {
stopRotation()
}
}
}
/**
* 按档位切换方向,重启动画集
*/
private fun restartRotationWithDirection() {
stopRotation() // 停止旧动画,记录当前角度
// 判断方向:当前档位 > 上一档位 = 加速;反之 = 减速
val needAccelerate = currentGear > previousGear
startRotationWithTransition(needAccelerate)
}
/**
* 启动动画集(含方向适配的过渡动画+匀速动画)
* @param accelerate 是否加速过渡(true=加速,false=减速)
*/
private fun startRotationWithTransition(accelerate: Boolean) {
// 1. 获取当前档位的匀速周期(毫秒/圈)
val uniformDuration = (getGearCycle() * 1000).toLong()
// 2. 计算过渡动画的绝对起止角度(避免相对角度歧义)
val transitionStartAngle = currentRotationAngle
val transitionEndAngle = currentRotationAngle + ROTATE_ANGLE_TRANSITION
// 3. 创建方向适配的过渡动画
val transitionAnim = RotateAnimation(
transitionStartAngle, // 起始角度:当前角度
transitionEndAngle, // 结束角度:当前角度+过渡角度
Animation.RELATIVE_TO_SELF, 0.5f, // 旋转中心:自身中心
Animation.RELATIVE_TO_SELF, 0.5f
).apply {
duration = TRANSITION_DURATION
// 按方向切换插值器
interpolator = if (accelerate) {
AccelerateDecelerateInterpolator() // 加速过渡(低档→高档)
} else {
DecelerateInterpolator() // 减速过渡(高档→低档)
}
fillAfter = true // 保持过渡后的角度
repeatCount = 0 // 仅执行1次
}
// 4. 创建匀速动画(绝对角度,无缝衔接)
val uniformAnim = RotateAnimation(
transitionEndAngle, // 起始角度:过渡动画结束角度
transitionEndAngle + 360f, // 结束角度:再转一圈
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f
).apply {
duration = uniformDuration
interpolator = LinearInterpolator() // 纯匀速
fillAfter = true
repeatCount = Animation.INFINITE // 无限循环
repeatMode = Animation.RESTART
}
// 5. 动画集串联(按顺序执行)
rotationAnimationSet = AnimationSet(true).apply {
addAnimation(transitionAnim)
addAnimation(uniformAnim)
isFillAfter = true
}
// 启动动画集
ivRotating.startAnimation(rotationAnimationSet)
}
/**
* 停止旋转(记录当前角度,用于下次衔接)
*/
private fun stopRotation() {
currentRotationAngle = ivRotating.rotation % 360f // 取余360,避免角度溢出
rotationAnimationSet?.cancel()
ivRotating.clearAnimation()
rotationAnimationSet = null
}
/**
* 获取当前档位的旋转周期(秒/圈)
*/
private fun getGearCycle(): Float {
return when (currentGear) {
1 -> 3f // 1挡:3秒/圈
2 -> 2f // 2挡:2秒/圈
3 -> 1f // 3挡:1秒/圈
else -> 3f
}
}
override fun onDestroy() {
super.onDestroy()
stopRotation()
}
}