private void setState(State state) {
    this.state = state;
    switch (state) {
      case PULL_TO_REFRESH:
        spinner.setVisibility(View.INVISIBLE);
        image.setVisibility(View.VISIBLE);
        text.setText(pullToRefreshText);

        if (showLastUpdatedText && lastUpdated != -1) {
          lastUpdatedTextView.setVisibility(View.VISIBLE);
          lastUpdatedTextView.setText(
              String.format(lastUpdatedText, lastUpdatedDateFormat.format(new Date(lastUpdated))));
        }

        break;

      case RELEASE_TO_REFRESH:
        spinner.setVisibility(View.INVISIBLE);
        image.setVisibility(View.VISIBLE);
        text.setText(releaseToRefreshText);
        break;

      case REFRESHING:
        setUiRefreshing();

        lastUpdated = System.currentTimeMillis();
        if (onRefreshListener == null) {
          setState(State.PULL_TO_REFRESH);
        } else {
          onRefreshListener.onRefresh();
        }

        break;
    }
  }
 private void setUiRefreshing() {
   spinner.setVisibility(View.VISIBLE);
   image.clearAnimation();
   image.setVisibility(View.INVISIBLE);
   text.setText(refreshingText);
 }
  @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);
  }