You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断ImageView移动指定距离的时机并修复Toast重复弹出问题

问题原因

  • AnimatorUpdateListener 会在动画执行过程中每帧回调一次,只要当前移动距离超过阈值,每帧都会触发一次Toast,导致多次弹出。
  • 若上一次点击触发的动画未结束就再次点击,旧动画的监听器还会持续运行,用旧的起始坐标计算距离,会出现距离未达标也弹出Toast的误触发问题。

修复方案

  1. 增加一个布尔标志位,标记本次动画是否已经弹出过Toast,避免同一次动画重复触发。
  2. 每次启动新动画前,先取消上一次正在运行的动画,移除旧的监听器,避免旧逻辑干扰。
  3. 可选优化:预先计算本次动画的总移动距离,如果总距离本身小于阈值,无需在帧回调中做判断,减少不必要的性能消耗。

修复后代码示例

private final int MAX_LENGTH = 420;
private int xRand, yRand;
private int xStart, yStart;
private boolean hasShownToast = false; // 新增标志位

private View unlimitePlayView;
private ImageView circle;
private ObjectAnimator animCircle; // 需将animCircle声明为成员变量

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
   super.onCreateView(inflater, container, savedInstanceState);
   unlimitePlayView = inflater.inflate(R.layout.fragment_tournament, container, false);
   circle = unlimitePlayView.findViewById(R.id.circle);

   circle.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
         // 先取消上一次动画,移除旧监听器
         if (animCircle != null && animCircle.isRunning()) {
             animCircle.cancel();
             animCircle.removeAllUpdateListeners();
         }
         // 重置标志位
         hasShownToast = false;
         
         xStart = (int) circle.getX();
         yStart = (int) circle.getY();
         xRand = new Random().nextInt(deviceWidth - circle.getWidth());
         yRand = new Random().nextInt(deviceHeight - circle.getHeight());
         
         // 可选:先计算总距离,不足阈值直接执行动画无需后续判断
         int totalDistance = (int) Math.sqrt(Math.pow(Math.abs(xRand - xStart), 2) + Math.pow(Math.abs(yRand - yStart), 2));
         if (totalDistance < MAX_LENGTH) {
             Path path = new Path();
             path.moveTo(xStart, yStart);
             path.lineTo(xRand, yRand);
             animCircle = ObjectAnimator.ofFloat(circle, "x", "y", path);
             animCircle.setDuration(1000);
             animCircle.start();
             return;
         }

         Path path = new Path();
         path.moveTo(xStart, yStart);
         path.lineTo(xRand, yRand);

         animCircle = ObjectAnimator.ofFloat(circle, "x", "y", path);
         animCircle.setDuration(1000);
         animCircle.start();

         animCircle.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
               float currentX = (float) valueAnimator.getAnimatedValue("x");
               float currentY = (float) valueAnimator.getAnimatedValue("y");
               int currentLength = (int) Math.sqrt(Math.pow(Math.abs(currentX - xStart), 2) + Math.pow(Math.abs(currentY - yStart), 2));
               // 增加标志位判断,仅第一次满足条件时弹出Toast
               if (currentLength > MAX_LENGTH && !hasShownToast) {
                  hasShownToast = true;
                  Toast.makeText(getActivity(), "DONE", Toast.LENGTH_SHORT).show();
               }
            }
         });
      }
   });
   return unlimitePlayView;
}

内容的提问来源于stack exchange,提问作者AnatolyS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 06:30:04