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 // 當(dāng)前檔位(默認(rèn)1擋)
? ? private var previousGear = 1 // 上一個檔位(用于判斷過渡方向)
? ? private var isRotating = false // 是否旋轉(zhuǎn)中
? ? private var currentRotationAngle = 0f // 當(dāng)前旋轉(zhuǎn)角度(銜接用)
? ? private var rotationAnimationSet: AnimationSet? = null // 動畫集
? ? // 固定參數(shù)
? ? private val TRANSITION_DURATION = 500L // 過渡時間(500ms)
? ? private val ROTATE_ANGLE_TRANSITION = 60f // 過渡動畫旋轉(zhuǎn)角度(平緩適配)
? ? 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() {
? ? ? ? // 檔位切換監(jiān)聽(核心:記錄上一檔位,判斷過渡方向)
? ? ? ? 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() // 按方向啟動過渡動畫
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 啟停開關(guān)監(jiān)聽
? ? ? ? switchRotate.setOnCheckedChangeListener { _, isChecked ->
? ? ? ? ? ? isRotating = isChecked
? ? ? ? ? ? if (isChecked) {
? ? ? ? ? ? ? ? // 首次啟動:默認(rèn)加速過渡(從靜止到當(dāng)前檔位)
? ? ? ? ? ? ? ? startRotationWithTransition(accelerate = true)
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? stopRotation()
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? /**
? ? * 按檔位切換方向,重啟動畫集
? ? */
? ? private fun restartRotationWithDirection() {
? ? ? ? stopRotation() // 停止舊動畫,記錄當(dāng)前角度
? ? ? ? // 判斷方向:當(dāng)前檔位 > 上一檔位 = 加速;反之 = 減速
? ? ? ? val needAccelerate = currentGear > previousGear
? ? ? ? startRotationWithTransition(needAccelerate)
? ? }
? ? /**
? ? * 啟動動畫集(含方向適配的過渡動畫+勻速動畫)
? ? * @param accelerate 是否加速過渡(true=加速,false=減速)
? ? */
? ? private fun startRotationWithTransition(accelerate: Boolean) {
? ? ? ? // 1. 獲取當(dāng)前檔位的勻速周期(毫秒/圈)
? ? ? ? val uniformDuration = (getGearCycle() * 1000).toLong()
? ? ? ? // 2. 計(jì)算過渡動畫的絕對起止角度(避免相對角度歧義)
? ? ? ? val transitionStartAngle = currentRotationAngle
? ? ? ? val transitionEndAngle = currentRotationAngle + ROTATE_ANGLE_TRANSITION
? ? ? ? // 3. 創(chuàng)建方向適配的過渡動畫
? ? ? ? val transitionAnim = RotateAnimation(
? ? ? ? ? ? transitionStartAngle, // 起始角度:當(dāng)前角度
? ? ? ? ? ? transitionEndAngle, // 結(jié)束角度:當(dāng)前角度+過渡角度
? ? ? ? ? ? Animation.RELATIVE_TO_SELF, 0.5f, // 旋轉(zhuǎn)中心:自身中心
? ? ? ? ? ? Animation.RELATIVE_TO_SELF, 0.5f
? ? ? ? ).apply {
? ? ? ? ? ? duration = TRANSITION_DURATION
? ? ? ? ? ? // 按方向切換插值器
? ? ? ? ? ? interpolator = if (accelerate) {
? ? ? ? ? ? ? ? AccelerateDecelerateInterpolator() // 加速過渡(低檔→高檔)
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? DecelerateInterpolator() // 減速過渡(高檔→低檔)
? ? ? ? ? ? }
? ? ? ? ? ? fillAfter = true // 保持過渡后的角度
? ? ? ? ? ? repeatCount = 0 // 僅執(zhí)行1次
? ? ? ? }
? ? ? ? // 4. 創(chuàng)建勻速動畫(絕對角度,無縫銜接)
? ? ? ? val uniformAnim = RotateAnimation(
? ? ? ? ? ? transitionEndAngle, // 起始角度:過渡動畫結(jié)束角度
? ? ? ? ? ? transitionEndAngle + 360f, // 結(jié)束角度:再轉(zhuǎn)一圈
? ? ? ? ? ? Animation.RELATIVE_TO_SELF, 0.5f,
? ? ? ? ? ? Animation.RELATIVE_TO_SELF, 0.5f
? ? ? ? ).apply {
? ? ? ? ? ? duration = uniformDuration
? ? ? ? ? ? interpolator = LinearInterpolator() // 純勻速
? ? ? ? ? ? fillAfter = true
? ? ? ? ? ? repeatCount = Animation.INFINITE // 無限循環(huán)
? ? ? ? ? ? repeatMode = Animation.RESTART
? ? ? ? }
? ? ? ? // 5. 動畫集串聯(lián)(按順序執(zhí)行)
? ? ? ? rotationAnimationSet = AnimationSet(true).apply {
? ? ? ? ? ? addAnimation(transitionAnim)
? ? ? ? ? ? addAnimation(uniformAnim)
? ? ? ? ? ? isFillAfter = true
? ? ? ? }
? ? ? ? // 啟動動畫集
? ? ? ? ivRotating.startAnimation(rotationAnimationSet)
? ? }
? ? /**
? ? * 停止旋轉(zhuǎn)(記錄當(dāng)前角度,用于下次銜接)
? ? */
? ? private fun stopRotation() {
? ? ? ? currentRotationAngle = ivRotating.rotation % 360f // 取余360,避免角度溢出
? ? ? ? rotationAnimationSet?.cancel()
? ? ? ? ivRotating.clearAnimation()
? ? ? ? rotationAnimationSet = null
? ? }
? ? /**
? ? * 獲取當(dāng)前檔位的旋轉(zhuǎn)周期(秒/圈)
? ? */
? ? 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()
? ? }
}