You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Expo Video Player时,跳转页面如何暂停或停止视频?

Hey there! I've dealt with this exact background video playback issue using Expo Video Player and React Navigation before—let's fix it for you. Here are two solid approaches to pause/stop the video when pushing a new screen onto the stack:

Approach 1: Use Navigation Lifecycle Hooks (Class Component)

Since your code looks like a class component, we can leverage React Navigation's blur and focus events to toggle the video's play state. Here's how to modify your component:

  1. Add a shouldPlay state to control the video's playback
  2. Attach listeners to the navigation events to update this state when the screen loses or regains focus
  3. Update the VideoPlayer to use the state for shouldPlay

Here's the modified code:

import React, { Component } from 'react';
import { Video } from 'expo-av';
import VideoPlayer from 'expo-video-player';
import { ScreenOrientation } from 'expo';

class VideoScreen extends Component {
  state = {
    shouldPlay: true,
  };

  componentDidMount() {
    // Listen for when the screen loses focus (when you push a new screen)
    this.blurListener = this.props.navigation.addListener('blur', () => {
      this.setState({ shouldPlay: false });
    });

    // Listen for when the screen regains focus (when you navigate back)
    this.focusListener = this.props.navigation.addListener('focus', () => {
      this.setState({ shouldPlay: true });
    });
  }

  componentWillUnmount() {
    // Clean up listeners to avoid memory leaks
    this.blurListener.remove();
    this.focusListener.remove();
  }

  render() {
    return (
      <VideoPlayer
        videoProps={{
          shouldPlay: this.state.shouldPlay,
          resizeMode: Video.RESIZE_MODE_CONTAIN,
          isMuted: false,
          source: { uri: this.props.navigation.state.params.video },
        }}
        isPortrait
        playFromPositionMillis={0}
        showFullscreenButton
        switchToLandscape={() => ScreenOrientation.allowAsync(ScreenOrientation.Orientation.LANDSCAPE)}
        switchToPortrait={() => ScreenOrientation.allowAsync(ScreenOrientation.Orientation.PORTRAIT)}
      />
    );
  }
}

export default VideoScreen;

Approach 2: Directly Control the Video Instance (More Granular Control)

If you want more control (like stopping the video completely instead of just pausing), you can get a reference to the underlying Video component and call its playback methods directly:

  1. Add a ref to the Video component via videoProps
  2. In the blur listener, call pauseAsync() or stopAsync() on the video ref

Modified code snippet:

// Inside your class component
state = {
  shouldPlay: true,
};

componentDidMount() {
  this.blurListener = this.props.navigation.addListener('blur', async () => {
    // Pause the video
    await this.videoRef.pauseAsync();
    // Or stop it entirely:
    // await this.videoRef.stopAsync();
    this.setState({ shouldPlay: false });
  });

  this.focusListener = this.props.navigation.addListener('focus', () => {
    this.setState({ shouldPlay: true });
  });
}

// In the VideoPlayer's videoProps
videoProps={{
  shouldPlay: this.state.shouldPlay,
  resizeMode: Video.RESIZE_MODE_CONTAIN,
  isMuted: false,
  source: { uri: this.props.navigation.state.params.video },
  ref: ref => this.videoRef = ref, // Add this line
}}

Bonus: Function Component Version (With useFocusEffect)

If you ever migrate to function components, here's how you'd handle it with React Navigation's useFocusEffect hook:

import React, { useState } from 'react';
import { Video } from 'expo-av';
import VideoPlayer from 'expo-video-player';
import { ScreenOrientation } from 'expo';
import { useFocusEffect } from '@react-navigation/native';

const VideoScreen = ({ navigation }) => {
  const [shouldPlay, setShouldPlay] = useState(true);

  useFocusEffect(
    React.useCallback(() => {
      // Resume playback when screen is focused
      setShouldPlay(true);

      // Pause when screen loses focus (cleanup function)
      return () => setShouldPlay(false);
    }, [])
  );

  return (
    <VideoPlayer
      videoProps={{
        shouldPlay,
        resizeMode: Video.RESIZE_MODE_CONTAIN,
        isMuted: false,
        source: { uri: navigation.params.video },
      }}
      isPortrait
      playFromPositionMillis={0}
      showFullscreenButton
      switchToLandscape={() => ScreenOrientation.allowAsync(ScreenOrientation.Orientation.LANDSCAPE)}
      switchToPortrait={() => ScreenOrientation.allowAsync(ScreenOrientation.Orientation.PORTRAIT)}
    />
  );
};

export default VideoScreen;

All these methods ensure that when you push a new screen onto the navigation stack, the current video pauses immediately instead of playing in the background. The first approach is great for most cases, while the second gives you more control if you need to stop the video entirely.

内容的提问来源于stack exchange,提问作者Cho Cho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:26:57