android视频适配与裁剪
2016-12-06 16:52
267 查看
https://my.oschina.net/u/1403288/blog/634051
摘要: android视频播放时对不同分辨率的手机的视频进行等比例缩放,然后裁剪掉一个方向上的多余部分,使之在不同手机上人的感观是不变的.
首先说下基本背景, 当我们使用android系统原生的VideoView播放视频时, 在XML中给它设置的一个尺寸, 但最终视频开始播放后, VideoView实际的尺寸可能并不是这个尺寸设置的大小. VideoView在测量自身的尺寸时会依据视频的真实尺寸来调整自己的大小, 遵循以下规则:
1. 实际视频在VideoView上播放时所有部分都是可见的,或缩小或放大, 总之一定要全部显示出来,不会裁剪实际视频.
2. 尽量保持实际视频的长宽比例, 具体是首先以我们用户定义的长度为标准, 等比例缩放视频大小, 直到长度达到我们定义的长度, 然后宽度(等比例缩放后的宽度)与我们定义的宽比较, 大于则以我们定义的宽度为准, 这样视频会在竖直方向上压缩, 最终播放时也就不会成比例了; 小于则它以视频缩放后的宽度为准, 这样它会比我们定义的高度小,最终播放的效果是等比例的.
最近开发有如下需求:
视频等比例放大,直至一边铺满VideoView(或屏幕)的某一边,另一边超出View的另一边,再移动到View的正中央,这样长边两边会被裁剪掉同样大小的区域,视频看起来不会变形,也即是:先把视频区(实际的大小显示区)与View(定义的大小)区的两个中心点重合, 然后等比例放大或缩小视频区,直至一条边与View的一条边相等,另一条边超过View的另一条边,这时再裁剪掉超出的边, 使视频区与View区大小一样. 这样在不同尺寸的手机上,视频看起来不会变形,只是水平或竖直方向的两端被裁剪了一些.
以上需求用系统的VideoView是无法达到的,所以要自定义VideoView.
最终我们扩展TextureView来自定义一个TextureVideoView, 并应用Matrix进行缩放, 也即是要求出变换的Matrix, 主要按以下步骤来即可求出变换矩阵, 这里直接贴出代码:
然后在OnVideoSizeChangedListener里面监听获取到了视频的实际尺寸后调用以上方法即可.
完整项目代码: https://github.com/linsea/MatrixScale
摘要: android视频播放时对不同分辨率的手机的视频进行等比例缩放,然后裁剪掉一个方向上的多余部分,使之在不同手机上人的感观是不变的.
首先说下基本背景, 当我们使用android系统原生的VideoView播放视频时, 在XML中给它设置的一个尺寸, 但最终视频开始播放后, VideoView实际的尺寸可能并不是这个尺寸设置的大小. VideoView在测量自身的尺寸时会依据视频的真实尺寸来调整自己的大小, 遵循以下规则:
1. 实际视频在VideoView上播放时所有部分都是可见的,或缩小或放大, 总之一定要全部显示出来,不会裁剪实际视频.
2. 尽量保持实际视频的长宽比例, 具体是首先以我们用户定义的长度为标准, 等比例缩放视频大小, 直到长度达到我们定义的长度, 然后宽度(等比例缩放后的宽度)与我们定义的宽比较, 大于则以我们定义的宽度为准, 这样视频会在竖直方向上压缩, 最终播放时也就不会成比例了; 小于则它以视频缩放后的宽度为准, 这样它会比我们定义的高度小,最终播放的效果是等比例的.
最近开发有如下需求:
视频等比例放大,直至一边铺满VideoView(或屏幕)的某一边,另一边超出View的另一边,再移动到View的正中央,这样长边两边会被裁剪掉同样大小的区域,视频看起来不会变形,也即是:先把视频区(实际的大小显示区)与View(定义的大小)区的两个中心点重合, 然后等比例放大或缩小视频区,直至一条边与View的一条边相等,另一条边超过View的另一条边,这时再裁剪掉超出的边, 使视频区与View区大小一样. 这样在不同尺寸的手机上,视频看起来不会变形,只是水平或竖直方向的两端被裁剪了一些.
以上需求用系统的VideoView是无法达到的,所以要自定义VideoView.
最终我们扩展TextureView来自定义一个TextureVideoView, 并应用Matrix进行缩放, 也即是要求出变换的Matrix, 主要按以下步骤来即可求出变换矩阵, 这里直接贴出代码:
//需求:视频等比例放大,直至一边铺满View的某一边,另一边超出View的另一边,再移动到View的正中央,这样长边两边会被裁剪掉同样大小的区域,视频看起来不会变形 //也即是:先把视频区(实际的大小显示区)与View(定义的大小)区的两个中心点重合, 然后等比例放大或缩小视频区,直至一条边与View的一条边相等,另一条边超过 //View的另一条边,这时再裁剪掉超出的边, 使视频区与View区大小一样. 这样在不同尺寸的手机上,视频看起来不会变形,只是水平或竖直方向的两端被裁剪了一些. private void transformVideo(int videoWidth, int videoHeight) { if (getHeight() == 0 || getWidth() == 0) { Log.d(TAG, "transformVideo, getHeight=" + getHeight() + "," + "getWidth=" + getWidth()); return; } float sx = (float) getWidth() / (float) videoWidth; float sy = (float) getHeight() / (float) videoHeight; Log.d(TAG, "transformVideo, sx=" + sx); Log.d(TAG, "transformVideo, sy=" + sy); float maxScale = Math.max(sx, sy); if (this.matrix == null) { matrix = new Matrix(); } else { matrix.reset(); } //第2步:把视频区移动到View区,使两者中心点重合. matrix.preTranslate((getWidth() - videoWidth) / 2, (getHeight() - videoHeight) / 2); //第1步:因为默认视频是fitXY的形式显示的,所以首先要缩放还原回来. matrix.preScale(videoWidth / (float) getWidth(), videoHeight / (float) getHeight()); //第3步,等比例放大或缩小,直到视频区的一边超过View一边, 另一边与View的另一边相等. 因为超过的部分超出了View的范围,所以是不会显示的,相当于裁剪了. matrix.postScale(maxScale, maxScale, getWidth() / 2, getResizedHeight() / 2);//后两个参数坐标是以整个View的坐标系以参考的 Log.d(TAG, "transformVideo, maxScale=" + maxScale); setTransform(matrix); postInvalidate(); Log.d(TAG, "transformVideo, videoWidth=" + videoWidth + "," + "videoHeight=" + videoHeight); }
然后在OnVideoSizeChangedListener里面监听获取到了视频的实际尺寸后调用以上方法即可.
完整项目代码: https://github.com/linsea/MatrixScale
相关文章推荐
- Android gc垃圾回收研究学习
- android Studio初体验
- genymotion无法下载或下载慢解决方法
- Android 中使用极光推送消息详细介绍
- 获取Android设备的方向
- Android 编程下的 TraceView 简介及其案例实战
- Android View绘制流程(二)
- Android View绘制流程
- RxAndroid学习指南
- android开发drawable-nodpi
- android 仿淘宝、京东商品详情页 向上拖动查看图文详情控件
- Android,iso接口调试-抓包调试接口
- 解决Android模拟器联网
- Android 截屏(Screenshot)代码流程小结
- [RK3288][Android6.0] 调试笔记 --- 如何区分两颗相同的USB UVC Camera
- 关于Android外设键盘导致系统输入法隐藏的解决方案
- 常用插件Android Layout ID Converter ----布局ID、控件自动获取
- android之获取屏幕宽度+均分屏幕
- Android自定义控件实战——水流波动效果的实现WaveView
- Android Studio一些常用的快捷键