@SuppressLint("NewApi")
  private void scroll(final float height) {
    if (mType == TYPE_INDICATOR || mType == TYPE_INDICATOR_WITH_HANDLE) {
      float move = height - (mScrollIndicator.getHeight() / 2);

      if (move < 0) move = 0;
      else if (move > getHeight() - mScrollIndicator.getHeight())
        move = getHeight() - mScrollIndicator.getHeight();

      if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
        mScrollIndicator.startAnimation(moveCompat(move));
      else mScrollIndicator.setTranslationY(move);
    }

    if (mType == TYPE_INDICATOR_WITH_HANDLE || mType == TYPE_POPUP_WITH_HANDLE) {
      mHandlebar.setSelected(true);
      moveHandlebar(height - (mHandlebar.getHeight() / 2));
    }

    int postition = (int) ((height / getHeight()) * mItemCount);
    if (mList instanceof ExpandableListView) {
      final int grouppos =
          ExpandableListView.getPackedPositionGroup(
              ((ExpandableListView) mList).getExpandableListPosition(postition));
      if (grouppos != -1) mGroupPosition = grouppos;
    }

    if (postition < 0) postition = 0;
    else if (postition >= mItemCount) postition = mItemCount - 1;
    mScrollIndicatorText.setText(mScrollable.getIndicatorForPosition(postition, mGroupPosition));
    mList.setSelection(mScrollable.getScrollPosition(postition, mGroupPosition));
  }
  private void bounceBackHeader() {
    int yTranslate =
        state == State.REFRESHING
            ? header.getHeight() - headerContainer.getHeight()
            : -headerContainer.getHeight() - headerContainer.getTop();

    TranslateAnimation bounceAnimation =
        new TranslateAnimation(
            TranslateAnimation.ABSOLUTE,
            0,
            TranslateAnimation.ABSOLUTE,
            0,
            TranslateAnimation.ABSOLUTE,
            0,
            TranslateAnimation.ABSOLUTE,
            yTranslate);

    bounceAnimation.setDuration(BOUNCE_ANIMATION_DURATION);
    bounceAnimation.setFillEnabled(true);
    bounceAnimation.setFillAfter(false);
    bounceAnimation.setFillBefore(true);
    bounceAnimation.setInterpolator(new OvershootInterpolator(BOUNCE_OVERSHOOT_TENSION));
    bounceAnimation.setAnimationListener(new HeaderAnimationListener(yTranslate));

    startAnimation(bounceAnimation);
  }
  private void resetHeader() {
    if (getFirstVisiblePosition() > 0) {
      setHeaderPadding(-header.getHeight());
      setState(State.PULL_TO_REFRESH);
      return;
    }

    if (getAnimation() != null && !getAnimation().hasEnded()) {
      bounceBackHeader = true;
    } else {
      bounceBackHeader();
    }
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (lockScrollWhileRefreshing
        && (state == State.REFRESHING || getAnimation() != null && !getAnimation().hasEnded())) {
      return true;
    }

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        if (getFirstVisiblePosition() == 0) previousY = event.getY();
        else previousY = -1;
        break;

      case MotionEvent.ACTION_UP:
        if (previousY != -1
            && (state == State.RELEASE_TO_REFRESH || getFirstVisiblePosition() == 0)) {
          switch (state) {
            case RELEASE_TO_REFRESH:
              setState(State.REFRESHING);
              bounceBackHeader();
              break;
            case PULL_TO_REFRESH:
              resetHeader();
              break;
            default:
              break;
          }
        }
        break;

      case MotionEvent.ACTION_MOVE:
        if (previousY != -1) {
          float y = event.getY();
          float diff = y - previousY;
          if (diff > 0) diff /= PULL_RESISTANCE;
          previousY = y;

          int newHeaderPadding = Math.max(Math.round(headerPadding + diff), -header.getHeight());

          if (newHeaderPadding != headerPadding && state != State.REFRESHING) {
            setHeaderPadding(newHeaderPadding);

            if (state == State.PULL_TO_REFRESH && headerPadding > 0) {
              setState(State.RELEASE_TO_REFRESH);

              image.clearAnimation();
              image.startAnimation(flipAnimation);
            } else if (state == State.RELEASE_TO_REFRESH && headerPadding < 0) {
              setState(State.PULL_TO_REFRESH);

              image.clearAnimation();
              image.startAnimation(reverseFlipAnimation);
            }

            return true;
          }
        }

        break;
    }

    return super.onTouchEvent(event);
  }