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 fromSwipeableViews
One 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
- Why not use it
currentIndex < 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
- Why keep it
SwipeableViews
The 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.