@Override
  public void draw(@NonNull Canvas canvas) {
    super.draw(canvas);
    if (leftGlow != null) {
      final int scrollX = getScrollX();
      if (!leftGlow.isFinished()) {
        final int restoreCount = canvas.save();
        final int height = getHeight() - getPaddingTop() - getPaddingBottom();

        canvas.rotate(270);
        canvas.translate(-height + getPaddingTop(), Math.min(0, scrollX));
        leftGlow.setSize(height, getWidth());
        if (leftGlow.draw(canvas)) {
          postInvalidate();
        }
        canvas.restoreToCount(restoreCount);
      }
      if (!rightGlow.isFinished()) {
        final int restoreCount = canvas.save();
        final int width = getWidth();
        final int height = getHeight() - getPaddingTop() - getPaddingBottom();

        canvas.rotate(90);
        canvas.translate(-getPaddingTop(), -(Math.max(getScrollRange(), scrollX) + width));
        rightGlow.setSize(height, width);
        if (rightGlow.draw(canvas)) {
          postInvalidate();
        }
        canvas.restoreToCount(restoreCount);
      }
    }
  }
  @Override
  public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
    switch (ev.getAction()) {
      case MotionEvent.ACTION_MOVE:
        float deltaX = prevX - ev.getX();

        if (!drag && Math.abs(deltaX) > mTouchSlop) {
          final ViewParent parent = getParent();
          if (parent != null) {
            parent.requestDisallowInterceptTouchEvent(true);
          }
          drag = true;
          if (deltaX > 0) {
            deltaX -= mTouchSlop;
          } else {
            deltaX += mTouchSlop;
          }
        }
        if (drag) {
          final int oldX = getScrollX();
          final int range = getScrollRange();
          boolean canOverscroll =
              overscrollMode == OVER_SCROLL_ALWAYS
                  || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);

          if (canOverscroll) {
            float pulledToY = oldX + deltaX;
            if (pulledToY < 0) {
              leftGlow.onPull(deltaX / getWidth(), 1.f - ev.getY() / getHeight());
              if (!rightGlow.isFinished()) rightGlow.onRelease();
            } else if (pulledToY > range) {
              rightGlow.onPull(deltaX / getWidth(), ev.getY() / getHeight());
              if (!leftGlow.isFinished()) leftGlow.onRelease();
            }
            if (leftGlow != null && (!leftGlow.isFinished() || !rightGlow.isFinished()))
              postInvalidate();
          }
        }
        break;
      case MotionEvent.ACTION_UP:
      case MotionEvent.ACTION_CANCEL:
        if (drag) {
          drag = false;

          if (leftGlow != null) {
            leftGlow.onRelease();
            rightGlow.onRelease();
          }
        }
        break;
    }
    prevX = ev.getX();

    return super.dispatchTouchEvent(ev);
  }