如何让RecyclerView项的抖动动画带延迟无限重复
解决方案
1. 调整抖动动画文件
首先修改res/anim/shake_animation.xml,将其改为单次抖动的完整动画,后续通过定时器控制每隔5秒重复执行:
<set xmlns:android="http://schemas.android.com/apk/res/android"> <rotate android:duration="50" <!-- 单次旋转的时长(从-2°到2°的时间) --> android:fromDegrees="-2" android:pivotX="50%" android:pivotY="50%" android:repeatCount="9" <!-- 重复次数,总抖动时长=50*(9+1)=500ms(可按需调整) --> android:repeatMode="reverse" android:toDegrees="2" /> </set>
如果需要控制单次抖动的总时长,直接计算:总时长 = duration * (repeatCount + 1),比如要单次抖动持续1秒,可设置duration="50"、repeatCount="19"(50*20=1000ms)。
2. 在RecyclerView Adapter中实现定时重复动画
由于RecyclerView存在View复用,必须在绑定View时启动定时任务,回收View时取消任务,避免动画混乱和内存泄漏:
步骤1:定义ViewHolder并持有定时任务
public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder> { private Context context; // 其他成员变量... public class ViewHolder extends RecyclerView.ViewHolder { private Handler shakeHandler; private Runnable shakeRunnable; public ViewHolder(@NonNull View itemView) { super(itemView); shakeHandler = new Handler(Looper.getMainLooper()); } } // Adapter其他方法... }
步骤2:绑定View时启动定时抖动
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { // 先取消当前View的旧任务,避免复用后重复执行 holder.shakeHandler.removeCallbacks(holder.shakeRunnable); // 定义抖动任务:执行一次抖动动画,5秒后重复 holder.shakeRunnable = new Runnable() { @Override public void run() { Animation shake = AnimationUtils.loadAnimation(context, R.anim.shake_animation); holder.itemView.startAnimation(shake); // 5秒后再次触发抖动 holder.shakeHandler.postDelayed(this, 5000); } }; // 立即执行第一次抖动 holder.shakeHandler.post(holder.shakeRunnable); }
步骤3:回收View时取消定时任务
@Override public void onViewRecycled(@NonNull ViewHolder holder) { super.onViewRecycled(holder); // 取消任务,避免内存泄漏和无效动画 holder.shakeHandler.removeCallbacks(holder.shakeRunnable); }
3. 可选:用ValueAnimator实现更灵活的抖动
如果觉得XML动画不够灵活,可直接用代码实现抖动,还能在动画结束后自动重置View状态:
private void startShakeAnimation(View view) { ValueAnimator animator = ValueAnimator.ofFloat(-2f, 2f); animator.setDuration(50); animator.setRepeatCount(9); animator.setRepeatMode(ValueAnimator.REVERSE); animator.addUpdateListener(animation -> { float rotateAngle = (float) animation.getAnimatedValue(); view.setRotation(rotateAngle); }); // 动画结束/取消时重置旋转角度 animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { view.setRotation(0); } @Override public void onAnimationCancel(Animator animation) { view.setRotation(0); } @Override public void onAnimationRepeat(Animator animation) {} }); animator.start(); }
然后在shakeRunnable中替换为调用这个方法即可:
holder.shakeRunnable = new Runnable() { @Override public void run() { startShakeAnimation(holder.itemView); holder.shakeHandler.postDelayed(this, 5000); } };
内容的提问来源于stack exchange,提问作者ttcreator
相关产品推荐
相关产品推荐

