What is thereact-swipeable-views

React-swipeable – Views is a touch screen swiping app for swiping the entire screen.

Use the pain points

The API does not meet business requirements

There isa scenario where you can swipe up only after the user has done something on the page but the disabled property provided by this component disables both

The area element at the bottom of the page is obscured by the action bar

Because the design and layout is based on the entire height of the browser, some elements located at the bottom are not visible under the influence of the address bar and action bar

Container height does not automatically match browser window height

For example, if you swipe up to the bottom, the browser address bar will disappear and the window size will change. If you do not re-adapt the height, the transform:translateY position will still be the same as the previous window height, causing the display to be incorrectly displayed

Native local scrolling and component racks

How to solve

The API does not meet business requirements

Basic idea: clone a source code to the local, to expand the source code

Extended attributes

Handle it in handleSwipeMove

  handleSwipeMove = event= >{... . . .const { axis, 
            children, 
            ignoreNativeScroll,
            onSwitching, 
            resistance,
            disableTouchUp,
            disableTouchDown
          } = this.props;
    const touch = applyRotationMatrix(event.touches[0], axis);
    const isTouchUp = touch.pageX - this.startX < 0
    const isTouchDown = touch.pageX - this.startX > 0
    if (disableTouchUp && isTouchUp) {
      console.log('isTouchUp',isTouchUp)
      return;
    }
    if (disableTouchDown && isTouchDown) {
      return; }... . . . }Copy the code

The area element at the bottom of the page is obscured by the action bar

Get the correct height

const [rightHeight, setRightHeight] = useState(0)   
useEffect(() = > {
     setRightHeight(window.innerHeight)                   
   },[])
Copy the code

Set the height of the component in swipeView

const getRightHeight = () = >{
	return {height:rightHeight}
}
<SwipeableViews
  resistance
  axis="y"
  animateHeight={true}
  >
  <APage style={getRightHeight()}/>
  <BPage style={getRightHeight()}/>
  <CPage style={getRightHeight()}/> 
</SwipeableViews>
Copy the code
const A|B|CPage =({style}) = > {

  return <div style={style}>. . . .</div>
}
Copy the code

Container height does not automatically match browser window height

Methods a

const [animateHeight, setAnimateHeight] = useState(true)
useEffect(() = > {
    window.onresize = function () {
      // Readjust the element height in swipeView and inform the component to readjust the height
      setRightHeight(window.innerHeight)
      setAnimateHeight(false)
      setTimeout(() = > {
        setAnimateHeight(true)},60)}}, [])Copy the code
const getRightHeight = () = >{
	return {height:rightHeight}
}
<SwipeableViews
  resistance
  axis="y"
  animateHeight={animateHeight}
  >
  <APage style={getRightHeight()}/>
  <BPage style={getRightHeight()}/>
  <CPage style={getRightHeight()}/> 
</SwipeableViews>
Copy the code

This is a touch screen fix for containerStyle height by changing animateHeight see source code

This method will cause the height to disappear instantly, making the page suddenly white screen (as shown below)

So, seeing this, I started to wonder if it would be easier to modify containerStyle

Method 2

const getRightHeight = () = >{
	return {height:rightHeight}
}

<SwipeableViews
  resistance
  axis="y"
  containerStyle={getRightHeight()}
  >
  <APage style={getRightHeight()}/>
  <BPage style={getRightHeight()}/>
  <CPage style={getRightHeight()}/> 
</SwipeableViews>
Copy the code

The root cause of the problem is that the component uses transform:translateY to determine the position of one screen, so the screen is continuous when the resize event occurs. The callback function we bind is executed, and the state changes to the page redrawing is an asynchronous behavior, so the page stays in the unadapted state and then changes to the adapted state.

Native local scrolling and component racks

If the inside of the container will disturb each other, put it outside the container

Take the last page fromSwipeableViewsOne copy from the container outside


<>
<SwipeableViews
  resistance
  axis="y"
  containerStyle={getRightHeight()} 
  >
  <APage style={getRightHeight()}/>
  <BPage style={getRightHeight()}/>
  <CPage style={getRightHeight()}/> 
</SwipeableViews>
<CPage style={getRightHeight()}/> 
</>
Copy the code

Go to page 3 and hide swipeView to show external page 3

const [currentIndex, setCurrentIndex] = useState(0)  

const onSwitching = (index) = > {
  setCurrentIndex(index)
}

<>
<SwipeableViews
   style={{display: currentIndex < 2 ? 'block' : 'none'}}
  resistance
  axis="y"
  containerStyle={getRightHeight()}
  onSwitching={onSwitching}
  >
  <APage style={getRightHeight()}/>
  <BPage style={getRightHeight()}/>
  <CPage style={getRightHeight()}/> 
</SwipeableViews>
<CPage style={{... getRightHeight(),display: currentIndex >= 2? 'block' : 'none'}}/> 
</>

Copy the code
  1. Why not use itcurrentIndex < 2? <SwipeableViews/>:<CPage>In this form?

A: This will cause the component to be re-rendered and the state of the slide position to be lost

  1. Why keep itSwipeableViewsThe inside of theCPage?

A: To ensure a smooth transition, the presence of an internal CPage will allow the transition animation to still exist when the critical state is switched to page 3

Add a touch event to page 3 to ensure that you can return from page 3 to page 2

// Parent returns to page 2
 const onTouchDownToLastPage = () = > {
    setCurrentIndex(1)}// Child
const CPage =({style,onTouchDownToLastPage}) = > {
    const onTouchStart = (e) = > {
    if(touchStartY.current === null) {
      setHasTouched(true)
    }
    touchStartY.current = e.changedTouches[0].pageY
  }
    const onTouchMove = (e) = > {

    let delta = e.changedTouches[0].pageY - touchStartY.current
    const dom = comicImgRef.current
    const scrollTop = comicWrap.current.scrollTop
    Abs (scrollTop) < 50
    if (delta > 0 && Math.abs(scrollTop) < 50) {
      onTouchDownToLastPage && onTouchDownToLastPage()
    }
  }

  return <div style={style} onTouchStart={onTouchStart} onTouchMove={onTouchMove}>. .<div className={styles.comic} ref={comicImgRef}></div>. .</div>
}
Copy the code

Other development issues

The bottom boot prompt should disappear when swiping, but when a finger slides over the icon, it prevents swiping

Cause analysis,

It is possible that the touch events between layers are not continuous because the display: None prompt is handled when sliding

The solution

Display: none to opacity: 0

Pay attention to

Consider whether it will block elements of the layer behind it

conclusion

Front-end development is against the sky, mutual encouragement.