Oly*_*Oly 3 webview android-webview react-native
我正在实现一个动态高度的WebView.我发现这个解决方案就像iOS上的魅力一样,并且不适用于android.该解决方案使用WV中的JS将标题设置为内容高度的值.这是代码:
...
this.state = {webViewHeight: 0};
...
<WebView
source={{html: this.wrapWevViewHtml(this.state.content)}}
style={{width: Dimensions.get('window').width - 20, height: this.state.webViewHeight}}
scrollEnabled={false}
javaScriptEnabled={true}
injectedJavaScript="window.location.hash = 1;document.title = document.height;"
onNavigationStateChange={this.onWebViewNavigationStateChange.bind(this)}
/>
...
onWebViewNavigationStateChange(navState) {
// navState.title == height on iOS and html content on android
if (navState.title) {
this.setState({
webViewHeight: Number(navState.title)
});
}
}
...
Run Code Online (Sandbox Code Playgroud)
但在android上,内部标题的值onWebViewNavigationStateChange等于页面内容.
我究竟做错了什么?
我也被这个困惑了.它确实有效,但很难调试它为什么不起作用,因为Android上的React Native WebViews没有启用Chrome远程调试.
我有两个问题:
我注入Webview的脚本包含一些单行注释,在Android上删除所有换行符(另一个错误?).它在WebView中导致语法错误.
在第一次调用时,标题内容确实是Webview的完整内容.不知道为什么,但后来称它为高度.所以只需处理这种情况.
这是我现在使用的代码,它适用于Android和iOS上的React Native 0.22
import React, {WebView, View, Text} from "react-native";
const BODY_TAG_PATTERN = /\<\/ *body\>/;
// Do not add any comments to this! It will break line breaks will removed for
// some weird reason.
var script = `
;(function() {
var wrapper = document.createElement("div");
wrapper.id = "height-wrapper";
while (document.body.firstChild) {
wrapper.appendChild(document.body.firstChild);
}
document.body.appendChild(wrapper);
var i = 0;
function updateHeight() {
document.title = wrapper.clientHeight;
window.location.hash = ++i;
}
updateHeight();
window.addEventListener("load", function() {
updateHeight();
setTimeout(updateHeight, 1000);
});
window.addEventListener("resize", updateHeight);
}());
`;
const style = `
<style>
body, html, #height-wrapper {
margin: 0;
padding: 0;
}
#height-wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
}
</style>
<script>
${script}
</script>
`;
const codeInject = (html) => html.replace(BODY_TAG_PATTERN, style + "</body>");
/**
* Wrapped Webview which automatically sets the height according to the
* content. Scrolling is always disabled. Required when the Webview is embedded
* into a ScrollView with other components.
*
* Inspired by this SO answer http://stackoverflow.com/a/33012545
* */
var WebViewAutoHeight = React.createClass({
propTypes: {
source: React.PropTypes.object.isRequired,
injectedJavaScript: React.PropTypes.string,
minHeight: React.PropTypes.number,
onNavigationStateChange: React.PropTypes.func,
style: WebView.propTypes.style,
},
getDefaultProps() {
return {minHeight: 100};
},
getInitialState() {
return {
realContentHeight: this.props.minHeight,
};
},
handleNavigationChange(navState) {
if (navState.title) {
const realContentHeight = parseInt(navState.title, 10) || 0; // turn NaN to 0
this.setState({realContentHeight});
}
if (typeof this.props.onNavigationStateChange === "function") {
this.props.onNavigationStateChange(navState);
}
},
render() {
const {source, style, minHeight, ...otherProps} = this.props;
const html = source.html;
if (!html) {
throw new Error("WebViewAutoHeight supports only source.html");
}
if (!BODY_TAG_PATTERN.test(html)) {
throw new Error("Cannot find </body> from: " + html);
}
return (
<View>
<WebView
{...otherProps}
source={{html: codeInject(html)}}
scrollEnabled={false}
style={[style, {height: Math.max(this.state.realContentHeight, minHeight)}]}
javaScriptEnabled
onNavigationStateChange={this.handleNavigationChange}
/>
{process.env.NODE_ENV !== "production" &&
<Text>Web content height: {this.state.realContentHeight}</Text>}
</View>
);
},
});
export default WebViewAutoHeight;
Run Code Online (Sandbox Code Playgroud)
作为要点https://gist.github.com/epeli/10c77c1710dd137a1335
| 归档时间: |
|
| 查看次数: |
4345 次 |
| 最近记录: |