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

Android React Native竖屏视频横屏模式下被裁切问题求助

我之前在做React Native项目时,刚好碰到过一模一样的Android WebView视频旋转裁切问题——iOS因为WebKit的适配逻辑本来就做得很到位,所以没啥问题,但Android这边的WebView确实需要手动调几个点才能搞定。给你整理了几个可行的方案,你可以根据自己的项目情况选:

方案一:给WebView加自适应缩放+JS监听动态调整样式

Android的WebView默认不会自动适配视频旋转后的宽高比,你可以通过注入JS监听视频全屏事件,再动态调整WebView的样式来解决:

  1. 先给React Native的WebView组件开启JS支持,注入监听代码:
import { WebView, Dimensions } from 'react-native';
import { useState } from 'react';

const VideoWebView = () => {
  const [webViewStyle, setWebViewStyle] = useState({ width: '100%', height: '100%' });

  // 注入JS监听视频全屏/旋转事件
  const injectedJS = `
    const video = document.querySelector('video');
    if (video) {
      // 监听webkit全屏变化(Android WebView用这个事件)
      video.addEventListener('webkitfullscreenchange', () => {
        const isFullscreen = document.webkitIsFullScreen;
        if (isFullscreen) {
          // 获取视频真实宽高比
          const ratio = video.videoWidth / video.videoHeight;
          window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'videoRotate', ratio }));
        } else {
          window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'videoReset' }));
        }
      });
    }
  `;

  // 处理WebView发来的消息,调整样式
  const handleMessage = (event) => {
    const data = JSON.parse(event.nativeEvent.data);
    const { width: screenWidth, height: screenHeight } = Dimensions.get('window');

    if (data.type === 'videoRotate') {
      // 根据视频比例计算合适的WebView尺寸,避免裁切
      const targetHeight = screenWidth / data.ratio;
      setWebViewStyle({
        width: screenWidth,
        height: targetHeight > screenHeight ? screenHeight : targetHeight,
        alignSelf: 'center'
      });
    } else if (data.type === 'videoReset') {
      // 恢复原样式
      setWebViewStyle({ width: '100%', height: '100%' });
    }
  };

  return (
    <WebView
      source={{ uri: '你的视频页面URL' }}
      style={webViewStyle}
      javaScriptEnabled={true}
      injectedJavaScript={injectedJS}
      onMessage={handleMessage}
      mediaPlaybackRequiresUserGesture={false} // 可选,避免视频播放需手动触发
    />
  );
};

export default VideoWebView;
  1. 同时如果你的项目有原生定制需求,可以在Android端给WebSettings加这两个关键配置:
WebSettings webSettings = webView.getSettings();
webSettings.setLoadWithOverviewMode(true); // 让WebView加载的内容自适应屏幕
webSettings.setUseWideViewPort(true); // 支持宽视图适配

方案二:替换WebView视频为React Native原生视频组件

如果WebView的适配成本太高,强烈建议把视频从WebView里抽出来,用react-native-video这类原生视频组件来播放——原生组件对双平台的视频旋转适配逻辑更完善,完全不会出现裁切问题:

  1. 先安装依赖:
npm install react-native-video --save
# 或者用yarn
yarn add react-native-video
  1. 直接使用组件,关键是设置resizeMode="contain"保证视频完整显示:
import Video from 'react-native-video';
import { Dimensions } from 'react-native';

const { width: screenWidth, height: screenHeight } = Dimensions.get('window');

const NativeVideoPlayer = () => {
  return (
    <Video
      source={{ uri: '你的视频URL' }}
      style={{ width: screenWidth, height: screenHeight }}
      resizeMode="contain" // 核心属性:保证视频完整显示,不会裁切
      fullscreenOrientation="landscape" // 指定全屏时为横屏
      controls={true}
    />
  );
};

export default NativeVideoPlayer;

方案三:自定义Android WebChromeClient处理全屏视频

如果必须保留WebView,可以通过自定义Android原生的WebChromeClient来处理视频全屏事件,手动控制视频的显示容器:

  1. 创建自定义WebViewManager类:
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;
import com.facebook.react.bridge.ThemedReactContext;
import com.facebook.react.views.webview.ReactWebViewManager;

public class CustomWebViewManager extends ReactWebViewManager {
  public static final String REACT_CLASS = "CustomWebView";

  @Override
  public String getName() {
    return REACT_CLASS;
  }

  @Override
  protected WebView createViewInstance(ThemedReactContext reactContext) {
    WebView webView = super.createViewInstance(reactContext);
    WebSettings webSettings = webView.getSettings();
    webSettings.setLoadWithOverviewMode(true);
    webSettings.setUseWideViewPort(true);

    // 自定义WebChromeClient处理视频全屏
    webView.setWebChromeClient(new WebChromeClient() {
      private View customVideoView;
      private CustomViewCallback customViewCallback;

      @Override
      public void onShowCustomView(View view, CustomViewCallback callback) {
        super.onShowCustomView(view, callback);
        if (customVideoView != null) {
          callback.onCustomViewHidden();
          return;
        }

        // 将视频视图添加到全屏容器
        FrameLayout rootView = (FrameLayout) reactContext.getCurrentActivity().getWindow().getDecorView();
        customVideoView = view;
        customViewCallback = callback;
        rootView.addView(customVideoView, new FrameLayout.LayoutParams(
          ViewGroup.LayoutParams.MATCH_PARENT,
          ViewGroup.LayoutParams.MATCH_PARENT
        ));

        // 开启全屏模式
        reactContext.getCurrentActivity().getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN);
      }

      @Override
      public void onHideCustomView() {
        super.onHideCustomView();
        if (customVideoView == null) return;

        // 移除视频视图,恢复原布局
        FrameLayout rootView = (FrameLayout) reactContext.getCurrentActivity().getWindow().getDecorView();
        rootView.removeView(customVideoView);
        customVideoView = null;
        customViewCallback.onCustomViewHidden();

        // 关闭全屏模式
        reactContext.getCurrentActivity().getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN);
      }
    });

    return webView;
  }
}
  1. 在React Native中注册这个自定义组件,替换默认WebView即可。这样当视频全屏时,Android会正确将视频铺满整个屏幕,不会出现裁切或滚动问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:12:33