如何通过下拉刷新在Expo Webview中刷新页面?

4

我使用Expo和React-Native制作了一个Webview应用程序,并观看YouTube视频。

首先,我创建了一个基本的应用程序,就像这样:

import * as React from 'react';
import { WebView } from 'react-native-webview';

export default class App extends React.Component {
  render() {
    return <WebView 
    source={{ uri: 'https://www.google.com' }} 
    allowsFullscreenVideo={true} 
    allowsBackForwardNavigationGestures={true}
    style={{ marginTop: 20 }} />;
  }
}

在 Android apk 中,“goBack” 按钮无法正常工作。如果我点击它,应用程序会直接关闭。但是我希望能够返回上一页。
因此,我进行了以下更改:
import * as React from 'react';
import {Component} from 'react';
import {View,BackHandler,Platform} from 'react-native';
import {WebView} from 'react-native-webview';

export default class App extends Component {
  constructor(props) {
    super(props);
  }
  webView = {
    canGoBack: false,
    ref: null,
  }

  onAndroidBackPress = () => {
    if (this.webView.canGoBack && this.webView.ref) {
      this.webView.ref.goBack();
      return true;
    }
    return false;
  }

  UNSAFE_componentWillMount() {
    if (Platform.OS === 'android') {
      BackHandler.addEventListener('hardwareBackPress', this.onAndroidBackPress);
    }
  }

  UNSAFE_componentWillUnmount() {
    if (Platform.OS === 'android') {
      BackHandler.removeEventListener('hardwareBackPress');
    }
  }

  render() {
    return (
      <View style={{flex:1}}>
        <WebView
          ref={(webView) => { this.webView.ref = webView; }}
          onNavigationStateChange={(navState) => { this.webView.canGoBack = navState.canGoBack; }}
          automaticallyAdjustContentInsets={false}
          source={{ uri: 'https://www.google.com' }}
          allowsFullscreenVideo={true}
          javaScriptEnabled={true}
          domStorageEnabled={true}
          startInLoadingState={true}
          style={{marginTop: 25}}
        />
    </View>
    )
  }
}

最终回退按钮可以使用了。如果我点击它,我就可以回到上一页。

但是我发现这个Webview应用程序无法刷新页面,所以我搜索了3天。这就是我期望的功能。在此链接中,您可以在下拉页面时看到圆形箭头。 https://reactnative.dev/docs/refreshcontrol?redirected

所以我混合了代码,但它不起作用。

import * as React from 'react';
import {Component} from 'react';
import {WebView} from 'react-native-webview';
import {
  ScrollView,View,BackHandler,Platform,
  RefreshControl,
  StyleSheet,
  Text,
  SafeAreaView,
} from 'react-native';
import Constants from 'expo-constants';


function wait(timeout) {
  return new Promise(resolve => {
    setTimeout(resolve, timeout);
  });
}

export default class App extends Component {
    
    
  const [refreshing, setRefreshing] = React.useState(false);

  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    wait(2000).then(() => setRefreshing(false));
  }, [refreshing]);

  constructor(props) {
    super(props);
  }
  webView = {
    canGoBack: false,
    ref: null,
  }

  onAndroidBackPress = () => {
    if (this.webView.canGoBack && this.webView.ref) {
      this.webView.ref.goBack();
      return true;
    }
    return false;
  }

  UNSAFE_componentWillMount() {
    if (Platform.OS === 'android') {
      BackHandler.addEventListener('hardwareBackPress', this.onAndroidBackPress);
    }
  }

  UNSAFE_componentWillUnmount() {
    if (Platform.OS === 'android') {
      BackHandler.removeEventListener('hardwareBackPress');
    }
  }

  render() {
    return (
    <SafeAreaView style={styles.container}>
      <ScrollView
        contentContainerStyle={styles.scrollView}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }
      >
        <WebView
          ref={(webView) => { this.webView.ref = webView; }}
          onNavigationStateChange={(navState) => { this.webView.canGoBack = navState.canGoBack; }}
          automaticallyAdjustContentInsets={false}
          source={{ uri: 'https://www.google.com' }} 
          allowsFullscreenVideo={true}
          javaScriptEnabled={true}
          domStorageEnabled={true}
          startInLoadingState={true}
          style={{marginTop: 25}}
        />
      </ScrollView>
    </SafeAreaView>
    )
  }
}

这是错误信息..

Error: /workspace/Human_Impact/App.js: Unexpected token (23:8)

  21 |
  22 |
> 23 |   const [refreshing, setRefreshing] = React.useState(false);
     |         ^
  24 |
  25 |   const onRefresh = React.useCallback(() => {
  26 |     setRefreshing(true);
Failed building JavaScript bundle.
  • 结论:我需要这些功能
  1. 如果我按一次Android硬件返回按钮,回到上一页,如果在很短的时间内按两次,则关闭应用程序。(Android)
  2. 如果我下拉,则刷新网页。(iOS / Android都适用)
3个回答

5

就像我之前说的那样,我尝试用这种方式来实现它,但是我只能向下滚动,当我需要向上滚动时,它会刷新。然而,我的结果并不好,因为RefreshControl总是启用状态,所以我根据之前提到的解决方案做了以下调整:

const [refreshing, setRefreshing] = useState(false);
const [refresherEnabled, setEnableRefresher] = useState(true);


  //Code to get scroll position
  const handleScroll = (event) =>  {
    console.log(Number(event.nativeEvent.contentOffset.y))
    const yOffset = Number(event.nativeEvent.contentOffset.y)
    if (yOffset === 0){
      console.log('top of the page')
      setEnableRefresher(true)
    }else{
      setEnableRefresher(false)
    }
  }
    
return (
    <SafeAreaView style={genericStyles.containerWebView}>
      <StatusBar backgroundColor={genericStyles.colors.BlueBg} barStyle={'light-content'} />
      <ScrollView style={genericStyles.scrollView} 
      contentContainerStyle={{flex: 1}}
      refreshControl={
        <RefreshControl 
          refreshing={refreshing}
          enabled={refresherEnabled}
          onRefresh={()=>{webViewRef.current.reload()}}
        />
      }>
        <WebView
          source={{ uri: your url }}
          ref={webViewRef}
          originWhitelist={['*']}
          allowsInlineMediaPlayback
          javaScriptEnabled
          scalesPageToFit
          mediaPlaybackRequiresUserAction={false}
          javaScriptEnabledAndroid
          useWebkit
          startInLoadingState={true}
          cacheEnabled
          onScroll={handleScroll}
        />
      </ScrollView>
    </SafeAreaView>
  )
}

5
首先,您可以为ScrollViewWebView添加样式:
container: {
  position : 'relative',
},
ScrollStyle: {
 backgroundColor : 'white',
 position: 'relative',
}

接下来,渲染您的ScrollViewWebView

<View style={{flex: 1}}>
    <ScrollView
        style = {styles.ScrollStyle}
        contentContainerStyle={{flex: 1}}
        refreshControl={
            <RefreshControl
              refreshing={false}
              onRefresh={this.yourFunctionReload} // exl in function : this.yourWebview.reload();
            />
        }>
        <Header />  
        <WebView
          style={styles.container}
            .....
         />
    </ScrollView>
</View>

注意:不要忘记导入View、ScrollView、RefreshControl和WebView


如何在声明之前在ScrollView中调用WebView引用? - Manyang
2
我尝试以这种方式实现,但是当我需要向上滚动时它只能向下滚动,并且会刷新。 - Hérick Raposo

2

一个演示,通过下拉刷新来查看答案,运行良好。感谢大家的帮助。

import {
  ScrollView,View,
  RefreshControl,
  StyleSheet,
} from 'react-native';
import { WebView } from 'react-native-webview';

function wait(timeout) {
  return new Promise(resolve => {
    setTimeout(resolve, timeout);
  });
}

export default function App() {

  const [refreshing, setRefreshing] = React.useState(false);
  const webViewRef = useRef()
  
  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    webViewRef.current.reload();
    wait(2000).then(() => setRefreshing(false));
  }, [refreshing]);

  return (
    <View style={{flex: 1}}>
    <ScrollView
        style = {styles.ScrollStyle}
        contentContainerStyle={{flex: 1}}
        refreshControl={
            <RefreshControl
              refreshing={false}
              onRefresh={onRefresh} // exl in function : this.yourWebview.reload();
            />
        }>
        <WebView
          ref = {webViewRef}
          automaticallyAdjustContentInsets={false}
          source={{ uri: 'https://www.google.com' }} 
          allowsFullscreenVideo={true}
          javaScriptEnabled={true}
          domStorageEnabled={true}
          startInLoadingState={true}
          style={styles.container}
        />
    </ScrollView>
</View>
  );
}

const styles = StyleSheet.create({
  container: {
    position : 'relative',
  },
  ScrollStyle: {
   backgroundColor : 'white',
   position: 'relative',
  }
});

1
我尝试以这种方式实现,但是我只能向下滚动,当我需要向上滚动时它会刷新。 - Hérick Raposo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接