「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」
Android 播放器自适应显示
在图片组件ImageView中,通过设置图片的scanType属性,就可以设置图片不同的显示模式。 在播放器视图TextureView、Surface中,应该怎么设置呢。这篇文章将的是常规播放器的缩放思想。
需求
应用程序为横屏,手机屏幕的分辨率为 400 * 800,宽800px,高400px。 视频的分辨率宽高不固定,但需要达到按比例填充手机屏幕的效果。 比如视频填充在手机上,是这个样子
其中黑色矩形代表手机屏幕,红色矩形代码视频的内容。
ImageView上的操作
上面的需求,如果是图片组件,就很简单,因为图片中有个属性可以很方便的我们进行设置,那就是scaleType属性,比如上面的需求,仅仅一行代码就能实现。
// android:scaleType="fitCenter"
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:src="@drawable/t3" />
scaleType的属性有很多值,比如常用的有
- center - 保持原图的大小,原图大小小于图片组件时,显示在图片组件的中间,大于图片组件时,超出部分截取
- centerCrop - 按原图比例放大,将图片组件填满,超出部分截取掉
- fitCenter - 原图等比例缩放,按比例填充图片组件,填充图片组件最短的一边
- fitXY - 完全填充图片组件,比例不匹配的情况下,进行拉伸
播放器的操作
由于播放器的组件使用的是TextureView或者SurfaceView组件,它没有scaleType属性,所以就需要动态计算宽高。
首先我们可以获取到屏幕的宽高属性,全面屏宽高的获取方法
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
Point point = new Point();
if (wm != null) {
wm.getDefaultDisplay().getRealSize(point);
}
LogWrapper.d("全面屏实际大小:" + point.toString());
int screenWidth = point.x;
int screenHeight = point.y;
然后可以从码流中得到视频的宽高,以h264格式为例,这样获取
MediaFormat currentFormat = mVideoCodec.getOutputFormat();
int mediaW = currentFormat.getInteger("width");
int mediaH = currentFormat.getInteger("height");
综上所述,我们拿到了屏幕宽、屏幕高、视频宽、视频高的具体值,接下来开始计算。
怎么判断是宽填充还是高填充呢?
用宽高比进行计算。
当screenHeight/screenWidth >= mediaH/mediaW 时,就是按照宽填充,反之则按照高填充。 (不明白的朋友多想一下)
进而按比例则得出显示到屏幕上的宽和高。
if (screenHeight * 1.0f / screenWidth >= mediaH * 1.0f / mediaW) {
// 宽填充
width = screenWidth;
height = (int) (screenWidth / (mediaW * 1.0f / mediaH));
} else {
// 高填充
height = screenHeight;
width = (int) (screenHeight * (mediaW * 1.0f / mediaH));
}
然后改变视图的大小即可
ViewGroup.LayoutParams surfaceLayoutParams = getVideoView().getLayoutParams();
// 将实际应该有的宽高赋值给LayoutParams
surfaceLayoutParams.width = width;
surfaceLayoutParams.height = height;
getVideoView().setLayoutParams(surfaceLayoutParams);