【问题标题】:Smooth scrolling with inertia and edge resistance/snapback具有惯性和边缘阻力/回弹的平滑滚动
【发布时间】:2011-02-15 11:30:35
【问题描述】:

我通过触摸拖动和多点触摸缩放为自定义视图实现了基本滚动。这很好用,但现在我想添加一些高级功能。

例如,在 Google 地图应用程序中,当您在屏幕上拖动时,停止拖动后它仍会继续移动一点(惯性)。并且某些浏览器(例如 iPad Safari)允许您将屏幕拖到比网站可见区域更远的地方,但随后屏幕会快速弹回网站边缘。

我现在想实现类似的东西,但要做到这一点,我需要更改活动屏幕区域触摸事件定期发生以执行动画。我该怎么做?

【问题讨论】:

    标签: java android touch


    【解决方案1】:

    使用OnGestureListener。要提供平滑滚动,请创建一个滚动条(在您的自定义视图中)。当手势侦听器检测到投掷事件时,设置滚动条。然后,覆盖您的自定义视图的 computeScroll() 方法。

    查看此示例以了解如何实现它。

    int lastX;
    int lastY;
    Scroller scroller;    
    @Override
    public void computeScroll() {
      if (scroller.computeScrollOffset()) {
        if (!scrolledLastFrame) {
          lastX = scroller.getStartX();
          lastY = scroller.getStartY();
        }
    
        int dx = scroller.getCurrX() - lastX;
        int dy = scroller.getCurrY() - lastY;
    
        lastX = scroller.getCurrX();
        lastY = scroller.getCurrY();
    
        doScroll(dx, dy);
        scrolledLastFrame = true;
      } else {
        scrolledLastFrame = false;
      }
    
    }    
    
    public void doFling(int startX, int startY, int velocityX, int velocityY,
        int minX, int maxX, int minY, int maxY) {
      scroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
      invalidate();
    }
    
    public void doScroll(int dx, int dy) {
      currentX+=dx;
      currentY+=dy;
    
      invalidate();
    }
    
    private class ProgramGestureListener extends SimpleOnGestureListener {
    
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
            float distanceX, float distanceY) {
    
          doScroll(distanceX, distanceY);
          return true;
        }
    
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
          int max_left = getMaxHorizontalScroll();
          int max_top = getMaxVerticalScroll();
          int min_left = getMinHorizontalScroll();
          int min_top = getMinVerticalScroll();
    
          int startX = getCurrentHorizontalScroll();
          int startY = getCurrentVerticalScroll();
    
          doFling(startX, startY, (int) -velocityX, (int) -velocityY,
              min_left, max_left, min_top, max_top);
    
          return true;
        }
      }
    

    【讨论】:

    • 我不知道 computeScroll(),这比我在 onDraw() 中使用 computeScrollOffset() 好得多。 +1
    • 谢谢!我已尝试根据您的回答实施解决方案,但由于某种原因未调用我的 computeScroll()。我必须以某种方式连接 Scroller 和 View 吗?
    • 要使用 GestureListener,还需要使用 GestureDetector。向检测器发送触摸事件并将 ProgramGestureListener 设置为检测器的侦听器。也许有用:stackoverflow.com/questions/937313/…
    【解决方案2】:

    使用Scroller类,我贴了一个使用here的例子。

    如果您使用的是 API 9,我认为可以使用 OverScroller

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多