我在react-native中安装了react-navigation 软件包
我已经实现了标签导航,其中之一是以webview格式实现的。
我的问题是,如果我按下Android上的后退物理按钮,则会从应用程序本身转到上一个选项卡,而不是从Web视图中返回。
我已经在互联网上为Webview应用了后退按钮,但是我没有这样做。
我尝试在调试时显示onNavigationStateChange日志,但是在第一次启动后加载url时,它并没有更新。这是我实现的代码:
import React from "react";
import {BackHandler} from "react-native";
import {WebView} from "react-native-webview";
class SermonScreen extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = {
header: null
};
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
_onNavigationStateChange(navState) {
console.log(navState);
this.setState({
canGoBack: navState.canGoBack
});
}
handleBackButton = () => {
console.log(this.state);
if (this.state.canGoBack === true) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<WebView
source={{uri: 'https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos' }}
ref={(webView) => this.webView = webView}
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
/>
);
}
}
export default SermonScreen;
答案 0 :(得分:1)
按照官方的webview文档,您可以尝试执行以下操作:https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes
通常情况下,您几乎就在那儿,但是YT导航的工作方式使其无法通过 onNavigationStateChange 捕获,这就是为什么我们注入一个JS代码来拦截这些哈希更改并发布消息的原因到父组件,然后在 onMessage 处理程序中捕获它,并正确设置状态变量。将 injectedJavaScript 和 onMessage 属性复制到您的示例中应该可以解决您的问题。
我为您准备了一个组件,该组件似乎可以满足您的要求:
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, { Fragment } from "react";
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
BackHandler,
StatusBar
} from "react-native";
import { WebView } from "react-native-webview";
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions
} from "react-native/Libraries/NewAppScreen";
class App extends React.Component {
constructor(props) {
super(props);
this.startingUrl =
"https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos";
this.handleBackButton = this.handleBackButton.bind(this);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
}
handleBackButton = () => {
console.log(this.state);
const { canGoBack } = this.state;
if (canGoBack) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<Fragment>
<WebView
source={{ uri: this.startingUrl }}
style={{ marginTop: 20 }}
ref={webView => (this.webView = webView)}
injectedJavaScript={`
(function() {
function wrap(fn) {
return function wrapper() {
var res = fn.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
}
}
history.pushState = wrap(history.pushState);
history.replaceState = wrap(history.replaceState);
window.addEventListener('popstate', function() {
window.ReactNativeWebView.postMessage('navigationStateChange');
});
})();
true;
`}
onMessage={({ nativeEvent: state }) => {
if (state.data === "navigationStateChange") {
// Navigation state updated, can check state.canGoBack, etc.
this.setState({
canGoBack: state.canGoBack
});
}
}}
/>
</Fragment>
);
}
}
export default App;
答案 1 :(得分:0)
上面的回答是完美的。不过,我将 canGoBack
的状态设置为 true;我收到了一个空错误,所以:
constructor(props) {
super(props);
this.startingUrl = "https://app.vethorcardpag.com.br/GIF/login/0/";
this.state = {
canGoBack : true
}
this.handleBackButton = this.handleBackButton.bind(this);
}