如何使用 React Navigation 包将 Screen 和 WebView 的后退按钮合并到 React Native 中?

问题描述 投票:0回答:1

我正在学习 React Native 中的导航,并且不知道如何有条件地使用一个后退按钮。 想要的行为是这样的 - 如果用户在屏幕之间导航,他可以按“返回”按钮,但如果其中一个屏幕包含 WebView 并且他已经访问了那里的几个页面,则用户将首先返回此 WebView 页面,然后返回屏幕。希望这是有道理的。 类似这样的东西:屏幕 A <- Screen B <- Screen C with WebView <- Webview Page 1 <- Webview Page 2

screenshot

应用程序屏幕

import React from 'react';
import {Pressable, StyleSheet, Text} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';

import HomeScreen from './src/screens/HomeScreen';
import WebViewScreen from './src/screens/WebViewScreen';
import ParamsScreen from './src/screens/ParamsScreen';

const Stack = createNativeStackNavigator();

function App(): React.JSX.Element {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={
          ({navigation}) => {}
        }>
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{title: 'Customized Header Home'}}
        />
        <Stack.Screen
          name="WebView Screen"
          component={WebViewScreen}
          options={({navigation, route}) => ({
            title: 'Webview',
            headerLeft: () => (
              <Pressable onPress={() => navigation.goBack()}>
                <Text style={{color: 'blue'}}>Go Back within Screens</Text>
              </Pressable>
            ),
          })}
        />
        <Stack.Screen name="Params Screen" component={ParamsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({});

export default App;

WebViewScreen

import {StyleSheet, Text, View, ActivityIndicator, Button} from 'react-native';
import React, {useRef, useState} from 'react';
import {WebView} from 'react-native-webview';

const WebViewScreen = ({navigation, route}) => {
  const webViewRef = useRef<WebView>(null);

  return (
    <>
      <View style={{flex: 0, alignItems: 'center', justifyContent: 'center'}}>
        <Text>WebView Screen</Text>
        <Button
          title="Go Back within WebView"
          onPress={() => webViewRef.current?.goBack()}
        />
      </View>
      <WebView
        source={{uri: 'https://google.com'}}
        startInLoadingState
        ref={webViewRef}
        renderLoading={() => (
          <View style={{flex: 1, alignItems: 'center'}}>
            <ActivityIndicator size="large" />
          </View>
        )}
        allowsBackForwardNavigationGestures
        onNavigationStateChange={navState => {}}
      />
    </>
  );
};

export default WebViewScreen;

const styles = StyleSheet.create({});

目前我已经设法拥有两个独立的工作按钮,但如果在标题中拥有一个后退按钮会更好。 我正在使用 Screen optionsonNavigationStateChange 参数,但有点迷失在那里。

我想我需要某种像这样的功能:

  const goBack = () => {
if (webViewRef.current) {
  webViewRef.current.goBack();
} else {
  navigation.goBack();
}

};

但不确定如何将其与 Stack.Navigator 集成

react-native react-navigation back-button
1个回答
0
投票

您可以通过在

headerLeft
中组合使用
onNavigationStateChange
WebViewScreen
来实现所需的行为。这是
WebViewScreen
的修改版本,应该可以帮助您实现组合后退功能:

import { StyleSheet, Text, View, ActivityIndicator, Button } from 'react-native';
import React, { useRef } from 'react';
import { WebView } from 'react-native-webview';

const WebViewScreen = ({ navigation, route }) => {
  const webViewRef = useRef();

  const handleNavigationStateChange = (navState) => {
    // Check if WebView can go back
    const canGoBack = navState.canGoBack;

    // Update the header left button based on WebView navigation
    navigation.setOptions({
      headerLeft: () => (
        <View style={{ marginLeft: 10 }}>
          <Button
            onPress={() => {
              if (canGoBack) {
                // If WebView can go back, go back in WebView
                webViewRef.current.goBack();
              } else {
                // If WebView cannot go back, go back in the navigation stack
                navigation.goBack();
              }
            }}
            title="Go Back"
            color="blue"
          />
        </View>
      ),
    });
  };

  return (
    <>
      <View style={{ flex: 0, alignItems: 'center', justifyContent: 'center' }}>
        <Text>WebView Screen</Text>
      </View>
      <WebView
        source={{ uri: 'https://google.com' }}
        startInLoadingState
        ref={webViewRef}
        renderLoading={() => (
          <View style={{ flex: 1, alignItems: 'center' }}>
            <ActivityIndicator size="large" />
          </View>
        )}
        allowsBackForwardNavigationGestures
        onNavigationStateChange={handleNavigationStateChange}
      />
    </>
  );
};

export default WebViewScreen;

const styles = StyleSheet.create({});

在此代码中,

handleNavigationStateChange
函数检查WebView是否可以返回(
canGoBack
)。然后它会相应地更新
headerLeft
按钮。如果WebView可以返回,按钮将触发
webViewRef.current.goBack()
,否则,将触发导航堆栈中的
navigation.goBack()
返回。

这样,标题中就有一个“返回”按钮,可以处理 WebView 和屏幕导航。

© www.soinside.com 2019 - 2024. All rights reserved.