When considering implementing a custom pull-down refresh component, it’s important to make it clear that this is a hack solution. It’s not that customizations are great, but customizable drop-down refreshes on Android have a slight lag (the way I did it). So stick with the applets as much as possible.

This implementation mainly refers to Alan’s components.

implementation

We split the page into the following structure

Normally the height of the drop-down refresh area is 0.

We then mark the start of slide by the scrollToUpeper event in the Scroll view.

Use touchStart to record the initial position of our finger.

Continuously calculate the finger movement distance by listening to the TouchMove event in the list area.

The Touchend event triggers the update event.

We divided the page into several states:

enum refreshStatus {
  INIT,
  PULL_DOWN,
  READY_REFRESH,
  LOADING,
  DONE
}
Copy the code

The general process is as follows:

  1. After the page loads, the INIT state.

  2. When the scrollToUpeper event of the ScrollView is triggered, we record a flag bit isUpper. When the Scroll event of the ScrollView is triggered, isUpper is denoted as false

  3. When our list page slides to the top and then pulls down, the page enters the PULL_DOWN state. A valid pull-down distance is usually set, called validHeight. When the pull-down height is insufficient, release your finger and the page will bounce back without refreshing.

  4. As we continue to pull down beyond the validHeight we enter READY_REFRESH state.

  5. Release your finger while in READY_REFRESH state to refresh the page and enter LOADING state.

  6. After the page is refreshed, the page enters the DONE state and the height of the refresh area changes to 0

We also need to set a maximum pull-down height and, in READY_REFRESH state, the maximum height for the finger to bounce back to the refresh area when it is released.

So far we can write the code touchend, touchstart, touchmove as follows :(detailed code)

  handleTouchMove(e) {
    const curTouch = e.touches[0]
    const moveY = (curTouch.pageY - this.lastTouchY) * 3.
    if(!this.isUpper ||
      moveY < 0 || 
      moveY > 2 * this.maxHeight ||
      this.state.refreshStatu === refreshStatus.LOADING
    ) {
      return
    }
    if(moveY < this.validHeight) {
      this.setState({
        refreshHeight: moveY,
        refreshStatu: refreshStatus.PULL_DOWN
      })
    } else {
      this.setState({
        refreshHeight: moveY,
        refreshStatu: refreshStatus.READY_REFRESH
      })
    }
  }
  handleTouchStart(e) {
    const curTouch = e.touches[0]
    this.lastTouchY = curTouch.pageY
  }
  handleTouchEnd() {
    this.lastTouchY = 0
    if(this.state.refreshStatu === refreshStatus.READY_REFRESH) {
      this.setState({
        refreshStatu: refreshStatus.LOADING,
        refreshHeight: this.maxHeight
      })
      if (this.props.onRefresh) {
        this.props.onRefresh()
      }
    } else {
      this.setState({
        refreshHeight: 0
      })
    }
  }
  handleScrollToUpeper() {
    this.isUpper = true
  }
  handleScroll() {
    this.isUpper = false
  }
Copy the code

In addition, we also need to add disableScroll: True configuration on the page of the call to solve the problem of ios entire page slide.

Compare the native drop-down refresh

  1. Android has a bit of a lag, ios and emulator experience is better.

  2. Page local drop-down refresh. The style of the refresh can also be customized.

conclusion

In fact, there is another way to achieve this in ios, which uses the ios Scroll view to pull down (rubber band effect) when it is pulled to the top. At this time, we can put the refreshed area on the scroll view area. Performance is definitely better than constantly computing height.

But there are two problems:

  1. It can’t be used locally on the page, because using locally would require disabling page scrolling, which in turn disables the ios rubber band effect and makes our pull-down refresh unusable

  2. The release of the finger had a slight rebound effect, which was harmless but still weird.

I’ll post this next time, or check out Alan’s blog, where he goes into a lot of detail, and I mostly used his code to implement it.