RN的几种嵌套滑动总结
安卓常用的几种嵌套滑动的组合:
ScrollView嵌套WebView
ScrollView需要高度才能渲染,直接嵌套会导致空白。
通过插入js的方式,在载入WebView的时候先传回WebView高度,::动态设置高度::
const BaseScript =
`
(function () {
var height = null;
function changeHeight() {
if (document.body.scrollHeight !== height) {
height = document.body.scrollHeight;
if (window.postMessage) {
// 如果是引用了react-native-webView
// 将window.postMessage替换成window.ReactNativeWebView.postMessage即可
window.postMessage(JSON.stringify({
type: 'setHeight',
height: height,
}))
}
}
}
setInterval(changeHeight, 1000);
} ())
`;
onMessage = (event) => {
try {
const action = JSON.parse(event.nativeEvent.data);
if (action.type === 'setHeight' && action.height > 0) {
this.setState({
height: action.height,
});
}
} catch (error) {
console.log(error);
}
}
<ScrollView>
<WebView
originWhitelist={['*']}
style={{ height: this.state.height, width: SCREEN_WIDTH }}
automaticallyAdjustContentInsets={false}
injectedJavaScript={BaseScript}
decelerationRate="normal"
scalesPageToFit
javaScriptEnabled
domStorageEnabled
scrollEnabled={false}
onMessage={this.onMessage}
/>
</ScrollView>
ScrollView嵌套FlatList
ScrollView嵌套FlatList,还想实现FlatList的下拉刷新和上拉加载,可以配合rn的手势系统PanResponder
涉及滑动的部分有ScrollView的scrollEnable属性,onScrollEndDrag方法,react-native组件PanResponder,及FlatList自己的下拉加载。
ScrollView嵌套FlatList,使用onScrollEndDrag方法监听滑动的位置,配合PanResponder手势。
当scrollOffset等于0时,手势下拉,则禁用ScrollView的滑动(scrollView的scrollEnable),此时可以实现flatList的自己的下拉刷新。
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
},
onPanResponderMove: (evt, gestureState) => {
if (gestureState.dy < 0 && !this.state.enableScrollViewScroll) {
this.setState({
enableScrollViewScroll: true,
});
}
if (this.state.scrollOffset === 0 && gestureState.dy > 0 && this.state.enableScrollViewScroll) {
this.setState({
enableScrollViewScroll: false,
});
}
},
onPanResponderRelease: (evt, gestureState) => {
},
onPanResponderTerminate: (evt, gestureState) => {
},
});
}
当scrollOffset和列表高度之和大于等于内容高度时,scrollView滑动到底部,调用分页的接口,实现上拉加载。
handleScrollEnd = (event) => {
const contentHeight = event.nativeEvent.contentSize.height;
const scrollViewHeight = event.nativeEvent.layoutMeasurement.height;
const scrollOffset = event.nativeEvent.contentOffset.y;
this.setState({
scrollOffset,
})
if (scrollOffset < 5) {
this.setState({
enableScrollViewScroll: false,
});
}
console.log('contentHeight', contentHeight);
console.log('scrollViewHeight', scrollViewHeight);
console.log('scrollOffset', scrollOffset);
console.log('是否滑动到底部', scrollOffset + scrollViewHeight >= contentHeight);
console.log('内容高度是否大于列表高度', contentHeight >= scrollViewHeight);
const isEndReached = scrollOffset + scrollViewHeight >= contentHeight; // 是否滑动到底部
const isContentFillPage = contentHeight >= scrollViewHeight; // 内容高度是否大于列表高度
// 实现下拉加载
if (isContentFillPage && isEndReached) {
// 获取分页数据的方法
}
};