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

如何自定义expo-av Video的useNativeControls并添加倍速、分辨率调节按钮

实现自定义播放器控制按钮的方案

你当前代码中启用了useNativeControls属性,调用的是系统原生播放控件,不支持插入自定义按钮,要实现倍速调节、分辨率切换的需求,关闭原生控件后自行封装自定义控制层即可,具体实现步骤如下:

第一步:新增状态管理并调整Video组件配置

首先添加对应状态变量管理播放速率、控制栏显隐、当前分辨率,再修改Video组件的属性配置:

// 新增状态
const [rate, setRate] = useState(1.0);
const [showControls, setShowControls] = useState(false);
const [currentResolution, setCurrentResolution] = useState("720p");

修改后的Video组件代码:

<Video
    key={videoId}
    ref={video}
    style={styles.videoPlayer}
    source={{
      uri: videofiles?.link,
    }}
    rate={rate}
    posterSource={{ uri: thumbnail }}
    usePoster={!isActivity}
    useNativeControls={false} // 关闭原生控件
    resizeMode={Video.RESIZE_MODE_CONTAIN}
    isLooping
    onPlaybackStatusUpdate={status => {
      statusChangeEvent(status);
    }}
    onFullscreenUpdate={onFullscreenUpdate}
    onPress={() => setShowControls(prev => !prev)} // 点击视频切换控制栏显隐
  />

第二步:叠加自定义控制层UI

给Video组件外层套一个相对定位的容器,同层级绝对定位叠加自定义控制栏,放入你需要的三个按钮:

<View style={styles.videoWrapper}>
  {/* 上述Video组件放在此处 */}
  {showControls && <View style={styles.controlsBar}>
    {/* 降低倍速按钮 */}
    <TouchableOpacity 
      onPress={() => setRate(prev => Math.max(0.5, prev - 0.25))}
      style={styles.controlBtn}
    >
      <Text style={{color: '#fff'}}>-0.25x</Text>
    </TouchableOpacity>
    {/* 显示当前倍速 */}
    <Text style={styles.rateText}>{rate}x</Text>
    {/* 升高倍速按钮 */}
    <TouchableOpacity 
      onPress={() => setRate(prev => Math.min(2.0, prev + 0.25))}
      style={styles.controlBtn}
    >
      <Text style={{color: '#fff'}}>+0.25x</Text>
    </TouchableOpacity>
    {/* 分辨率切换按钮 */}
    <TouchableOpacity 
      onPress={async () => {
        // 切换分辨率逻辑,可根据自己的业务调整分辨率选项
        const newRes = currentResolution === "720p" ? "1080p" : "720p";
        const status = await video.current.getStatusAsync();
        let currentPosition = 0;
        if(status.isLoaded) currentPosition = status.positionMillis;
        // 替换为对应分辨率的视频地址,getResUrl为你自己实现的地址映射方法
        videofiles.link = getResUrl(newRes);
        setCurrentResolution(newRes);
        // 切换后回到之前的播放进度
        setTimeout(() => {
          video.current.setPositionAsync(currentPosition);
        }, 100)
      }}
      style={styles.controlBtn}
    >
      <Text style={{color: '#fff'}}>{currentResolution}</Text>
    </TouchableOpacity>
    {/* 可自行补充播放/暂停、进度条、全屏等其他控制功能 */}
  </View>}
</View>

第三步:补充对应样式

const styles = StyleSheet.create({
  videoWrapper: {
    position: 'relative',
    width: '100%',
    aspectRatio: 16/9
  },
  videoPlayer: {
    width: '100%',
    height: '100%'
  },
  controlsBar: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    height: 50,
    backgroundColor: 'rgba(0,0,0,0.7)',
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 16,
    gap: 16
  },
  controlBtn: {
    paddingHorizontal: 8,
    paddingVertical: 4,
    backgroundColor: '#333',
    borderRadius: 4
  },
  rateText: {
    color: '#fff',
    minWidth: 40,
    textAlign: 'center'
  }
})

注意事项

  • 可给控制栏添加自动隐藏逻辑,用户操作后3秒无交互自动隐藏,提升使用体验
  • 提前做好不同分辨率的视频地址映射,避免切换时请求失败
  • 可根据业务需求调整倍速可选区间,示例中设置的是0.5x到2x的范围

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:54:03