2025-11-25

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()

? ? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容