react-native - 如何返回 webview?我在 react-native 中使用 react-navigation 包

标签 react-native react-native-android react-navigation

我安装了react-navigation 打包在 react-native

我已经实现了选项卡导航,其中一个是以 webview 格式实现的。

我的问题是,如果我按下 Android 上的后退物理按钮,我会从应用程序本身转到上一个选项卡,而不是从 web View 返回。

我已经在互联网上为 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;

最佳答案

按照官方 webview 文档,您可以尝试这样做:https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes

一般来说,您几乎就在那里,但是 YT 导航的工作方式使得无法通过 onNavigationStateChange 捕获,这就是为什么我们注入(inject)一个 JS 代码来拦截这些哈希更改并向父组件发布消息,然后我们将其捕获在里面onMessage 处理程序并正确设置状态变量。将注入(inject)的 JavaScript 和 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;

关于react-native - 如何返回 webview?我在 react-native 中使用 react-navigation 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55122592/

相关文章:

react-native - 返回时React Navigation重新渲染上一页

react-native - Flow Promise 此类型与 undefined undefined 不兼容

javascript - 如何在 react-native 中重叠图像

ios - 如何在不更改 React Native 中的路由的情况下更改 NavigatorIOS 的标题

react-native - 进程 'command ' npx.cmd'' 以非零退出值 1 react native 构建问题完成

react-native - 有没有办法导航到两个不同的应用程序容器 react native

javascript - 如何在 native react 中将 stackNavigation 与抽屉导航一起使用并在 stackNavigation 组件中使用toggleDrawer()

react-native - React Native 命令行 'processDebugGoogleServices' 错误

image - React Native Image resizeMode vs resizeMethod

react-native - 我在 react native 中遇到错误 - fontFamily "ionicons"不是系统字体