React Native中Expo VideoPlayer全屏保留自定义控件问题咨询
React Native视频全屏时自定义控件消失问题
我在开发React Native应用时,希望实现视频播放并支持全屏功能。加载组件时一切正常,但进入全屏后,我添加的自定义控件会消失,取而代之的是系统默认控件。以下是我的代码:
import React, { useState, useRef } from "react"; import { View, StyleSheet, Dimensions, Text, } from "react-native"; import { ResizeMode } from "expo-av"; import GeneralStyles from "../../styles/GeneralStyles"; import { LinearGradient } from "expo-linear-gradient"; import { ScrollView } from "react-native-gesture-handler"; import VideoPlayer from "expo-video-player"; const MyComponent = () => { const lastVideo = useRef(null); const [fullScreenMode, setFullScreenMode] = useState(ResizeMode.COVER); const { width } = Dimensions.get("window"); return ( <LinearGradient colors={["#FFFFFF", "#FFEFE3", "#FFE1E1", "#FFFFFF"]}> <ScrollView style={GeneralStyles.mainContainer}> <View style={[styles.videoContainer]}> <View style={{ padding: 10, borderWidth: 1, backgroundColor: 'black', borderRadius: 10 }}> <VideoPlayer videoProps={{ shouldPlay: false, resizeMode: fullScreenMode, source: { uri: "https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4", }, ref: lastVideo, }} style={{ height: width * 1.5, width: width * 0.9, videoBackgroundColor: "transparent", controlsBackgroundColor: "black", }} header={ <Text style={{ color: "#FFF", padding: 10 }}> The title </Text> } autoHidePlayer={{ autoHide: true, duration: 1000 }} activityIndicator={{ size: "large", color: "#FFF" }} slider={{ thumbTintColor: "#FFF", margin: 10, minimumTrackTintColor: "#E50000", maximumTrackTintColor: "#FFF", }} fullscreen={{ visible: true, enterFullscreen: async () => { try { setFullScreenMode(ResizeMode.CONTAIN); await lastVideo.current.presentFullscreenPlayer(); } catch (error) { console.log(error); } }, exitFullscreen: async () => { try { setFullScreenMode(ResizeMode.COVER); await lastVideo.current.dismissFullscreenPlayer(); } catch (error) { console.log(error); } }, controls: { hide: true, }, }} /> </View> <View style={styles.dateContainer}> <Text style={styles.date}>17/06/2023</Text> </View> </View> </ScrollView> </LinearGradient> ); }; const styles = StyleSheet.create({ videoContainer: { alignSelf: "center", marginBottom: 20, }, date: { fontSize: 15, textAlign: "center", fontWeight: 300, color: "rgba(255, 255, 255, 1)", padding: 5, paddingLeft: 10, }, dateContainer: { position: "absolute", top: 10, right: 10, width: "auto", justifyContent: "center", alignItems: "center", backgroundColor: "rgba(0, 0, 0, 0.7)", borderRadius: 10, }, });
我了解到使用presentFullscreenPlayer()时,即使设置useNativeControls为false,仍会使用默认控件。请问如何让自定义控件在全屏时显示?是否需要更换库,或者有其他解决方法?
解决方案
方法1:手动实现"伪全屏",规避系统原生全屏API
系统的presentFullscreenPlayer()会强制接管视频渲染并使用原生控件,这是Expo Video的固有限制。可以通过调整组件布局模拟全屏效果:
- 新增
isFullScreen状态控制页面元素显示 - 进入全屏时:
- 锁定屏幕为横向(需借助
expo-screen-orientation库) - 隐藏ScrollView及其他非视频元素
- 将视频容器设为占满整个屏幕
- 锁定屏幕为横向(需借助
- 退出全屏时恢复原有布局与屏幕方向
核心修改代码示例:
import { ScreenOrientation } from 'expo-screen-orientation'; const MyComponent = () => { const lastVideo = useRef(null); const [fullScreenMode, setFullScreenMode] = useState(ResizeMode.COVER); const [isFullScreen, setIsFullScreen] = useState(false); const { width, height } = Dimensions.get("window"); const enterFullscreen = async () => { try { await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE_LEFT); setFullScreenMode(ResizeMode.CONTAIN); setIsFullScreen(true); // 保持视频播放状态 await lastVideo.current.playAsync(); } catch (error) { console.log(error); } }; const exitFullscreen = async () => { try { await ScreenOrientation.unlockAsync(); setFullScreenMode(ResizeMode.COVER); setIsFullScreen(false); await lastVideo.current.pauseAsync(); } catch (error) { console.log(error); } }; return ( <LinearGradient colors={["#FFFFFF", "#FFEFE3", "#FFE1E1", "#FFFFFF"]}> {!isFullScreen ? ( <ScrollView style={GeneralStyles.mainContainer}> <View style={[styles.videoContainer]}> <View style={{ padding: 10, borderWidth: 1, backgroundColor: 'black', borderRadius: 10 }}> <VideoPlayer videoProps={{ shouldPlay: false, resizeMode: fullScreenMode, source: { uri: "https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4" }, ref: lastVideo, useNativeControls: false }} style={{ height: width * 1.5, width: width * 0.9 }} header={<Text style={{ color: "#FFF", padding: 10 }}>The title</Text>} autoHidePlayer={{ autoHide: true, duration: 1000 }} activityIndicator={{ size: "large", color: "#FFF" }} slider={{ thumbTintColor: "#FFF", margin: 10, minimumTrackTintColor: "#E50000", maximumTrackTintColor: "#FFF", }} fullscreen={{ visible: true, enterFullscreen, exitFullscreen }} /> </View> <View style={styles.dateContainer}> <Text style={styles.date}>17/06/2023</Text> </View> </View> </ScrollView> ) : ( <View style={{ flex: 1, backgroundColor: 'black' }}> <VideoPlayer videoProps={{ shouldPlay: true, resizeMode: fullScreenMode, source: { uri: "https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4" }, ref: lastVideo, useNativeControls: false }} style={{ flex: 1 }} header={<Text style={{ color: "#FFF", padding: 10 }}>The title</Text>} autoHidePlayer={{ autoHide: true, duration: 1000 }} activityIndicator={{ size: "large", color: "#FFF" }} slider={{ thumbTintColor: "#FFF", margin: 10, minimumTrackTintColor: "#E50000", maximumTrackTintColor: "#FFF", }} fullscreen={{ visible: true, exitFullscreen }} /> </View> )} </LinearGradient> ); };
方法2:更换视频播放库
若不想手动实现伪全屏,可选择支持自定义全屏的第三方库:
- react-native-video:完全自定义控件与全屏逻辑,不依赖系统原生全屏API,灵活性更高
- react-native-video-player:基于
react-native-video封装,自带全屏和自定义控件能力
注意:react-native-video在Expo项目中需使用兼容版本或配合expo-av适配。
关键注意事项
- 必须在
videoProps中设置useNativeControls: false,彻底禁用原生控件 - 伪全屏方案需配置
expo-screen-orientation权限,处理屏幕方向的锁定与恢复 - 切换全屏时需保持视频播放状态,可通过
playAsync()/pauseAsync()控制
内容的提问来源于stack exchange,提问作者DFG
相关产品推荐
相关产品推荐

