react native 关于ScrollView嵌套WebView的交互问题,这个问题很早前就解决过了,但是发现好多人有这方面问题,之前是因为写资讯的需求在网页下面还得显示评论等内容所以发现的这个问题,写个我的解决方案吧!
首先常规下,WebView正常的展示网页:
<SafeAreaView style={styles.safeAreaView}>
<WebView
style={{ flex: 1 }}
source={{ uri: 'https://bbs.reactnative.cn/category/3/blogs' }}
/>
</SafeAreaView>
但是用ScrollView嵌套时,就会加载空白:
<SafeAreaView style={styles.safeAreaView}>
<ScrollView style={{ flex: 1 }}>
<WebView
style={{ flex: 1 }}
source={{ uri: 'https://bbs.reactnative.cn/category/3/blogs' }}
/>
</ScrollView>
</SafeAreaView>
此时我们需要设置webview的展示的宽高,就可以正常显示:
<SafeAreaView style={styles.safeAreaView}>
<ScrollView style={{ flex: 1 }}>
<WebView
style={{ height: Dimensions.get('window').height, width:Dimensions.get('window').width}}
source={{ uri: 'https://bbs.reactnative.cn/category/3/blogs' }}
/>
</ScrollView>
</SafeAreaView>
虽说正常显示了,但是交互上出现了问题,ios模拟器上效果正常,Android模拟器不能正常的上下滚动展示内容:
那么如何解决这个问题呢?我的方案是:
1. 首先使用WebView的属性injectedJavaScript
注入脚本代码:(设置js字符串,在网页加载之前注入的一段JS代码。)
下面的脚本代码设置了type和获取了页面内容的高度:
const injectedJavaScript = `
(function () {
var height = null;
function changeHeight() {
if (document.body.scrollHeight != height) {
height = document.body.scrollHeight;
if (window.postMessage) {
window.postMessage(JSON.stringify({
type: 'setHeight',
data: height,
}))
}
}
}
setInterval(changeHeight, 100);
}());
`;
2. 接着可以使用WebView的属性onMessage通过脚本代码调用window.postMessage方法时可以触发此属性对应的函数,从而实现网页和RN之间的数据交换。
<SafeAreaView style={styles.safeAreaView}>
<ScrollView style={{ flex: 1 }}>
<WebView
style={{ height: this.state.height,width:Dimensions.get('window').width}}
source={{ uri: 'https://bbs.reactnative.cn/category/3/blogs' }}
injectedJavaScript={injectedJavaScript}
onMessage={(event) => {
try {
const action = JSON.parse(event.nativeEvent.data);
const { type, data } = action;
if (this.OnMessageActions.hasOwnProperty(type)) {
this.OnMessageActions[type](data);
}
} catch (error) {
console.log('ShowWebViewPage onMessage错误', error);
}
}}
/>
</ScrollView>
</SafeAreaView>
如果你的RN项目版本升级到0.59.9时,上面处理ios端会出现问题,onMessage处理方式改为
onMessage={(event) => {
try {
const eventData = Platfrom.OS === ‘iOS’ ?
decodeURIComponent(decodeURIComponent(event.nativeEvent.data))
: event.nativeEvent.data;
const action = JSON.parse(eventData);
const { type, data } = action;
if (Object.prototype.hasOwnProperty.call(this.OnMessageActions, type)) {
this.OnMessageActions[type](data);
}
} catch (error) {
Console.error('ShowWebViewPage onMessage错误', error);
}
}}
3. 将获取的高度动态设置给WebView
扫描二维码关注公众号,回复:
10652245 查看本文章
OnMessageActions = {
setHeight: (height) => {
if (height > 0) {
this.setState({ height });
}
},
};
最终解决了ScrollView嵌套WebView出现的滚动问题。