@Override
 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   super.onScrollChanged(l, t, oldl, oldt);
   if (listener != null) {
     listener.onScrollChanged(this, l, t, oldl, oldt);
   }
 }
  @Override
  public void computeScroll() {
    if (scroller.computeScrollOffset()) {
      if (this.onScrollChangedListener != null) {

        onScrollChangedListener.OnHorizontalScrollChanged(
            this, SCROLLING, scroller.getCurrX() - offX);
        onScrollChangedListener.OnVerticalScrollChanged(
            this, SCROLLING, scroller.getCurrY() - offY);
      }
      offX = scroller.getCurrX();
      offY = scroller.getCurrY();
      invalidate();
    } else {
      if (scrolling) {
        if (this.onScrollChangedListener != null) {

          onScrollChangedListener.OnHorizontalScrollChanged(this, SCROLL_END, 0);
          onScrollChangedListener.OnVerticalScrollChanged(this, SCROLL_END, 0);
        }
        scrolling = false;
      }
    }
  }
 @Override
 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   super.onScrollChanged(l, t, oldl, oldt);
   listener.onScrollChanged(l, t, oldl, oldt);
 }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);
    if (velocityTracker == null) velocityTracker = VelocityTracker.obtain();
    velocityTracker.addMovement(event);
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      if (!scroller.isFinished()) scroller.abortAnimation();
      lastX = event.getX();
      lastY = event.getY();

      draggingX = draggingY = false;
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
      if (draggingX || Math.abs(event.getX() - lastX) > touchSlop) {
        this.offX += (event.getX() - lastX);
        if (this.getWidth() > worldWidth) offX = 0;
        else if (offX > 0) offX = 0;
        else if (offX < this.getWidth() - worldWidth) offX = this.getWidth() - worldWidth;

        if (!draggingX) {
          if (this.onScrollChangedListener != null)
            onScrollChangedListener.OnHorizontalScrollChanged(
                this, SCROLL_START, (int) (event.getX() - lastX));
        } else {
          if (this.onScrollChangedListener != null)
            onScrollChangedListener.OnHorizontalScrollChanged(
                this, SCROLLING, (int) (event.getX() - lastX));
        }
        lastX = event.getX();
        draggingX = true;
      }
      if (draggingY || Math.abs(event.getY() - lastY) > touchSlop) {
        this.offY += (event.getY() - lastY);
        if (this.getHeight() > worldHeight) offY = 0;
        else if (offY > 0) offY = 0;
        else if (offY < this.getHeight() - worldHeight) offY = this.getHeight() - worldHeight;

        if (!draggingY) {
          if (this.onScrollChangedListener != null)
            onScrollChangedListener.OnVerticalScrollChanged(
                this, SCROLL_START, (int) (event.getY() - lastY));
        } else {
          if (this.onScrollChangedListener != null)
            onScrollChangedListener.OnVerticalScrollChanged(
                this, SCROLLING, (int) (event.getY() - lastY));
        }
        lastY = event.getY();
        draggingY = true;
      }
      if (draggingX || draggingY) this.invalidate();
    } else if (event.getAction() == MotionEvent.ACTION_UP
        || event.getAction() == MotionEvent.ACTION_CANCEL) {
      velocityTracker.computeCurrentVelocity(1000, maximumVelocity);
      float vx = velocityTracker.getXVelocity();
      float vy = velocityTracker.getYVelocity();
      int minX, minY;
      boolean flip = false;
      float minTan = 3.0f;
      // 当斜率大于minTan时忽略小方向的速度
      if (Math.abs(vx) < minimumVelocity
          || this.getWidth() > worldWidth
          || Math.abs(vy / vx) > minTan) {
        vx = 0;
        if (this.getWidth() > worldWidth) minX = 0;
        else minX = this.getWidth() - worldWidth;
      } else {
        minX = this.getWidth() - worldWidth;
        flip = true;
      }
      if (Math.abs(vy) < minimumVelocity
          || this.getHeight() > worldHeight
          || Math.abs(vx / vy) > minTan) {
        vy = 0;
        if (this.getHeight() > worldHeight) minY = 0;
        else minY = this.getHeight() - worldHeight;
      } else {
        minY = this.getHeight() - worldHeight;
        flip = true;
      }
      if (flip) {
        scrolling = true;
        scroller.fling(offX, offY, (int) vx, (int) vy, minX, 0, minY, 0);
        this.invalidate();
      } else {
        if (this.onScrollChangedListener != null) {
          if (draggingX) {
            onScrollChangedListener.OnHorizontalScrollChanged(this, SCROLL_END, 0);
          }
          if (draggingY) {
            onScrollChangedListener.OnVerticalScrollChanged(this, SCROLL_END, 0);
          }
        }
      }
      draggingX = draggingY = false;
      velocityTracker.recycle();
      velocityTracker = null;
      this.invalidate();
    }
    return true;
  }