博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ExoPlayer实现设置画面比例功能
阅读量:2083 次
发布时间:2019-04-29

本文共 8438 字,大约阅读时间需要 28 分钟。

设置视频画面比例

之前用的EXOplayer1.0版本的,是GitHub上面别人修改过的一个开源demo,里面直接就集成了画面比例的方法,叫做setScaleType,最近播放器要升级发现原来Exoplayer1.0版本的setScaleType方法对于EXOplayer2.0并不适用后来参考IjkPlayerView的方法,找到了一个叫做setMeasuredDimension()的方法,这个方法相信大家并不陌生哦。这里做下简单介绍吧:setMeasuredDimension(width,height)接受width和height两个参数用于设置当前view的大小。其实说白了设置视频画面比例不就是重新设置view的大小吗?对吧。下面直接贴上设置画面比例的逻辑吧,核心就是如何计算view的宽和高,完了就调用上面的setMeasuredDimension(width,height)方法设置一下即可。

详细讲解参考博客:

@Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        Log.i(TAG, "onMeasure " + " [" + this.hashCode() + "] ");        int mVideoRotationDegree = (int) getRotation();        int mVideoWidth = mVideoSize.x;        int mVideoHeight = mVideoSize.y;        Log.i(TAG, "videoWidth = " + mVideoWidth + ", videoHeight = " + mVideoHeight + ", " +                "viewRotation = " + mVideoRotationDegree);        // 如果旋转了90°或270°则宽高测量值进行互换        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {            int tempMeasureSpec = widthMeasureSpec;            widthMeasureSpec = heightMeasureSpec;            heightMeasureSpec = tempMeasureSpec;        }        // 获取默认的测量宽高值        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);        if (mCurrentAspectRatio == AR_MATCH_PARENT) {            // 在 AR_MATCH_PARENT 模式下直接用原始测量值            width = widthMeasureSpec;            height = heightMeasureSpec;        } else if (mVideoWidth > 0 && mVideoHeight > 0) {            int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);            int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);            int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);            int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);            // modify,把&&操作符换为||            if (widthSpecMode == View.MeasureSpec.AT_MOST || heightSpecMode == View.MeasureSpec                    .AT_MOST) {                // 测量宽高比,对应的视图的宽高比                float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize;                // 显示宽高比,要显示的视频宽高比                float displayAspectRatio;                // 这里计算显示宽高比                switch (mCurrentAspectRatio) {                    case AR_16_9_FIT_PARENT:                        // 16:9                        displayAspectRatio = 16.0f / 9.0f;                        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)                            displayAspectRatio = 1.0f / displayAspectRatio;                        break;                    case AR_4_3_FIT_PARENT:                        // 4:3                        displayAspectRatio = 4.0f / 3.0f;                        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)                            displayAspectRatio = 1.0f / displayAspectRatio;                        break;                    case AR_ASPECT_FIT_PARENT:                    case AR_ASPECT_FILL_PARENT:                    case AR_ASPECT_WRAP_CONTENT:                    default:                        // 按视频来源宽高比                        displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;//                        if (mVideoSarNum > 0 && mVideoSarDen > 0)//                            displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen;                        break;                }                // 是否要显示视频宽度比例较大                boolean shouldBeWider = displayAspectRatio > specAspectRatio;                // 这里确定最终宽高                switch (mCurrentAspectRatio) {                    case AR_ASPECT_FIT_PARENT:                    case AR_16_9_FIT_PARENT:                    case AR_4_3_FIT_PARENT:                        if (shouldBeWider) {                            // too wide, fix width;宽度比较大,固定宽度,使用测量宽度,按显示比例缩放高度                            width = widthSpecSize;                            height = (int) (width / displayAspectRatio);                        } else {                            // too high, fix height;高度比较大,固定高度,使用测量高度,按显示比例缩放宽度                            height = heightSpecSize;                            width = (int) (height * displayAspectRatio);                        }                        break;                    case AR_ASPECT_FILL_PARENT: // 填充满控件模式                        if (shouldBeWider) {                            // not high enough, fix height;宽度比较大,固定高度,缩放宽度                            height = heightSpecSize;                            width = (int) (height * displayAspectRatio);                        } else {                            // not wide enough, fix width;高度比较大,固定宽度,缩放高度                            width = widthSpecSize;                            height = (int) (width / displayAspectRatio);                        }                        break;                    case AR_ASPECT_WRAP_CONTENT:                    default:                        if (shouldBeWider) {                            // too wide, fix width;和第一个类似,这里取 (mVideoWidth, widthSpecSize) 最小的值                            width = Math.min(mVideoWidth, widthSpecSize);                            height = (int) (width / displayAspectRatio);                        } else {                            // too high, fix height                            height = Math.min(mVideoHeight, heightSpecSize);                            width = (int) (height * displayAspectRatio);                        }                        break;                }            } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View                    .MeasureSpec.EXACTLY) {                // the size is fixed                width = widthSpecSize;                height = heightSpecSize;                // for compatibility, we adjust size based on aspect ratio                // 这里做的是缩小某一边的大小以达到和视频原始尺寸的比例                if (mVideoWidth * height < width * mVideoHeight) {                    width = height * mVideoWidth / mVideoHeight;                } else if (mVideoWidth * height > width * mVideoHeight) {                    height = width * mVideoHeight / mVideoWidth;                }            } else if (widthSpecMode == View.MeasureSpec.EXACTLY) {                // only the width is fixed, adjust the height to match aspect ratio if possible                width = widthSpecSize;                height = width * mVideoHeight / mVideoWidth;                if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {                    // couldn't match aspect ratio within the constraints,不让高度超出测量高度                    height = heightSpecSize;                }            } else if (heightSpecMode == View.MeasureSpec.EXACTLY) {                // only the height is fixed, adjust the width to match aspect ratio if possible                height = heightSpecSize;                width = height * mVideoWidth / mVideoHeight;                if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {                    // couldn't match aspect ratio within the constraints,不让宽度超出测量宽度                    width = widthSpecSize;                }            } else {                // neither the width nor the height are fixed, try to use actual video size                width = mVideoWidth;                height = mVideoHeight;                if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {                    // too tall, decrease both width and height                    height = heightSpecSize;                    width = height * mVideoWidth / mVideoHeight;                }                if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {                    // too wide, decrease both width and height                    width = widthSpecSize;                    height = width * mVideoHeight / mVideoWidth;                }            }        } else {            // no size yet, just adopt the given spec sizes        }        setMeasuredDimension(width, height);    }

好了,简单吧。下面我还是要强烈安利一下——IjkPlayerView

目前集成的主要功能:

沉浸式全屏播放,隐藏状态栏和虚拟键如果有的话,用的时候有些需要注意的地方放后面说;

弹幕功能,包括发射弹幕和弹幕基本样式设置:大小、颜色和类型(顶部、底部和滚动弹幕),效果同Bilibili;
竖屏和横屏的切换,其实就是小屏和全屏的切换,提供了重力感应来切换竖横屏功能;
触屏控制,竖直方向左边控制亮度,右边控制声音,水平方向控制播放进度;
三指旋转缩放,当三个手指触屏时就可以进行视频界面的旋转缩放,效果同Bilibili;
视频源切换,可设置流畅、清晰、高清、超清和1080p等5种视频源;
视频宽高比例设置,包括16:9、4:3、视频内嵌填充界面和填充屏幕等4种;
记录上次播放进度的跳转功能;
其它的如截屏功能,电池电量显示,时间显示,播放常亮,跑马灯标题和锁屏处理;

怎么样?还是很全面的吧,应该就差个gif动图截取的功能了,有兴趣的好好学习下吧,O(∩_∩)O~

转载地址:http://cgcqf.baihongyu.com/

你可能感兴趣的文章
hibernate 时间段查询
查看>>
java操作cookie 实现两周内自动登录
查看>>
Tomcat 7优化前及优化后的性能对比
查看>>
Java Guava中的函数式编程讲解
查看>>
Eclipse Memory Analyzer 使用技巧
查看>>
tomcat连接超时
查看>>
强引用 软引用 弱引用 虚引用
查看>>
数据类型 java转换
查看>>
"NetworkError: 400 Bad Request - http://172.16.47.117:8088/rhip/**/####t/approval?date=976
查看>>
mybatis 根据 数据库表 自动生成 实体
查看>>
C结构体、C++结构体、C++类的区别
查看>>
进程和线程的概念、区别和联系
查看>>
CMake 入门实战
查看>>
Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题
查看>>
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
(PAT 1019) General Palindromic Number (进制转换)
查看>>
(PAT 1080) Graduate Admission (排序)
查看>>