Android中如何暂停与恢复圆形ImageView的旋转动画?
实现圆形ImageView旋转/暂停切换(停在当前位置)
嘿,这个需求其实很常见,咱们分两种方案来实现,优先推荐更简洁的属性动画方案,如果你坚持要用原来的补间动画也给你补全方法~
方案一:用ObjectAnimator(属性动画,推荐)
属性动画比补间动画更灵活,原生支持暂停和恢复,而且直接操作View的属性,暂停时会精准停在当前旋转角度,完全符合你的需求。修改你的MainActivity代码如下:
import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.view.animation.LinearInterpolator; public class MainActivity extends AppCompatActivity { private ObjectAnimator rotateAnimator; private ImageView imageview; private Button button1; private boolean isRotating = false; // 标记当前是否正在旋转 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageview = findViewById(R.id.imageview); button1 = findViewById(R.id.button1); // 创建旋转属性动画:操作ImageView的rotation属性,从0到360度 rotateAnimator = ObjectAnimator.ofFloat(imageview, "rotation", 0f, 360f); rotateAnimator.setDuration(10000); // 10秒转一圈 rotateAnimator.setInterpolator(new LinearInterpolator()); // 匀速旋转 rotateAnimator.setRepeatCount(ValueAnimator.INFINITE); // 无限循环 rotateAnimator.setRepeatMode(ValueAnimator.RESTART); // 每次循环从0开始(这里因为是360度,其实和REVERSE效果一样) button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isRotating) { // 当前正在旋转,点击暂停 rotateAnimator.pause(); } else { // 当前已暂停,点击恢复/启动 if (rotateAnimator.isPaused()) { rotateAnimator.resume(); } else { rotateAnimator.start(); } } // 切换状态标记 isRotating = !isRotating; } }); } }
为什么推荐这个方案?
- 不用写xml动画文件,代码内直接配置更灵活
- 原生支持
pause()和resume(),无需手动计算角度,逻辑极简 - 属性动画直接修改View的
rotation属性,状态更稳定,不会出现补间动画的绘制层偏移问题
方案二:基于你原有的补间动画xml实现
如果你不想放弃原来的xml动画配置,我们可以通过记录当前旋转角度,每次暂停后重新创建从当前角度开始的动画:
首先在MainActivity中添加几个状态变量:
import android.os.Bundle; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.RotateAnimation; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { private Animation cd1; private ImageView imageview; private Button button1; private boolean isRotating = false; private float currentDegree = 0f; // 记录当前暂停时的角度 private long startTime; // 记录动画开始的时间,用于计算当前进度 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageview = findViewById(R.id.imageview); button1 = findViewById(R.id.button1); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isRotating) { // 暂停动画:先取消当前动画,计算并记录当前角度 cd1.cancel(); long elapsedTime = System.currentTimeMillis() - startTime; float progress = (float) elapsedTime / cd1.getDuration(); // 计算当前旋转的总角度(因为是无限循环,取模360得到当前实际角度) currentDegree = (360 * progress) % 360; isRotating = false; } else { // 启动/恢复旋转:从当前角度开始创建新的动画 cd1 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.cd_player1); RotateAnimation rotateAnim = (RotateAnimation) cd1; // 设置动画的起始角度为当前记录的角度,结束角度为当前角度+360 rotateAnim.setFromDegrees(currentDegree); rotateAnim.setToDegrees(currentDegree + 360); // 记录动画开始时间,用于后续计算进度 startTime = System.currentTimeMillis(); imageview.startAnimation(cd1); isRotating = true; } } }); } }
注意点:
- 每次暂停后都要重新加载动画并修改起始/结束角度,逻辑比属性动画繁琐
- 补间动画是作用在View的绘制层,并非真正修改View的属性,所以如果View有位移或其他操作,可能会出现视觉偏移问题
内容的提问来源于stack exchange,提问作者Binh Cao
相关产品推荐
相关产品推荐

