Android Studio中如何实现视频自动裁剪适配竖屏VideoView?
Android竖屏VideoView自动中心裁剪视频实现方案
原生VideoView默认使用FIT_CENTER适配逻辑,会出现留黑边、无法自动裁剪超出内容的问题,以下两种方案都可以直接实现目标效果:横屏视频自动裁去左右两侧内容居中显示、竖屏视频适配时裁去上下超出部分,所有超出控件范围的内容都会被隐藏,和短视频信息流的视频显示效果一致。
方案一:自定义中心裁剪VideoView(无额外依赖,轻量)
不需要引入第三方库,直接继承原生VideoView重写测量逻辑,实现和ImageView.CENTER_CROP一致的适配效果,加载Firebase视频的逻辑和原生用法完全兼容。
- 新建
CenterCropVideoView类,复制以下代码:
public class CenterCropVideoView extends VideoView { public CenterCropVideoView(Context context) { super(context); } public CenterCropVideoView(Context context, AttributeSet attrs) { super(context, attrs); } public CenterCropVideoView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int viewWidth = MeasureSpec.getSize(widthMeasureSpec); int viewHeight = MeasureSpec.getSize(heightMeasureSpec); int videoWidth = getVideoWidth(); int videoHeight = getVideoHeight(); // 视频未加载完成时走默认测量逻辑 if (videoWidth == 0 || videoHeight == 0) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } float viewAspectRatio = (float) viewWidth / viewHeight; float videoAspectRatio = (float) videoWidth / videoHeight; int calcWidth, calcHeight; // 横屏视频(宽高比大于控件):按控件高度铺满,裁剪左右多余部分 if (videoAspectRatio > viewAspectRatio) { calcHeight = viewHeight; calcWidth = (int) (viewHeight * videoAspectRatio); } // 竖屏视频(宽高比小于控件):按控件宽度铺满,裁剪上下多余部分 else { calcWidth = viewWidth; calcHeight = (int) (viewWidth / videoAspectRatio); } setMeasuredDimension(calcWidth, calcHeight); } }
- 布局文件中替换原生
VideoView为自定义控件,按需求设置竖屏尺寸即可:
<com.your.package.CenterCropVideoView android:id="@+id/cropVideoView" android:layout_width="match_parent" android:layout_height="400dp" android:layout_centerHorizontal="true"/>
- 视频加载时增加适配兜底,避免部分机型首次加载获取视频宽高失败:
CenterCropVideoView videoView = findViewById(R.id.cropVideoView); videoView.setVideoURI(Uri.parse("你的Firebase视频地址")); // 视频准备完成后重新触发布局测量,保证裁剪逻辑生效 videoView.setOnPreparedListener(mediaPlayer -> { videoView.requestLayout(); videoView.start(); });
方案二:使用AndroidX Media3 ExoPlayer实现(推荐长期迭代场景)
如果后续需要扩展视频缓存、倍速播放、清晰度切换等能力,可以直接用官方维护的Media3播放器,自带中心裁剪配置,不需要自定义控件。
- 先在模块级
build.gradle引入依赖:
implementation "androidx.media3:media3-exoplayer:1.2.1" implementation "androidx.media3:media3-ui:1.2.1"
- 布局中添加
PlayerView,通过resize_mode直接开启中心裁剪效果:
<androidx.media3.ui.PlayerView android:id="@+id/playerView" android:layout_width="match_parent" android:layout_height="400dp" app:resize_mode="zoom" app:use_controller="false" android:layout_centerHorizontal="true"/>
- 初始化播放器加载Firebase视频即可,
zoom模式会自动完成居中裁剪,超出控件的内容自动隐藏:
PlayerView playerView = findViewById(R.id.playerView); ExoPlayer player = new ExoPlayer.Builder(this).build(); playerView.setPlayer(player); MediaItem mediaItem = MediaItem.fromUri(Uri.parse("你的Firebase视频地址")); player.setMediaItem(mediaItem); player.prepare(); player.play();
注意事项
- 两种方案都是显示层的裁剪调整,不会修改原视频文件,不需要提前对Firebase上存储的视频做转码、裁剪预处理。
- 裁剪逻辑默认居中对齐,横屏视频会自动保留中间核心画面、裁掉左右两侧超出部分,完全匹配需求。
- 使用自定义VideoView方案时,父布局请保持默认
android:clipChildren="true"配置,否则超出控件范围的视频内容无法被裁剪隐藏。
内容的提问来源于stack exchange,提问作者Sergio26
相关产品推荐
相关产品推荐

