前言
視頻播放有一個較為蛋疼的問題,那就是尺寸適配.如果不做尺寸適配視頻將會變形拉伸或者壓縮.下面我就介紹個人實現的算法.
滿足一邊的算法
滿足一邊?你可能是疑問是什么意思.意思是就是始終將視頻的高度或者寬度的其中一個鋪滿對應屏幕的高度或者寬度.然后在將另外一個高或寬按比例求出合適的尺寸,其實這跟與攝像頭的求出合適的分辨率預覽思想是類似的.
另外,在視頻高大於寬且屏幕是豎屏情況下,鋪滿高度,但是會計算寬度,但是計算后多多少少視頻寬度與屏幕寬度不一致,但是其實已經很接近比例了.我們可以接受視頻的輕微拉伸,來滿足視頻鋪滿屏幕的情況,下面的算法就是做了這種優化.
代碼部分:
/** * 修改預覽View的大小,以用來適配屏幕 */ public void changeVideoSize() { int videoWidth = mMediaPlayer.getVideoWidth(); int videoHeight = mMediaPlayer.getVideoHeight(); int deviceWidth = getResources().getDisplayMetrics().widthPixels; int deviceHeight = getResources().getDisplayMetrics().heightPixels; Log.e(TAG, "changeVideoSize: deviceHeight="+deviceHeight+"deviceWidth="+deviceWidth); float devicePercent = 0; //下面進行求屏幕比例,因為橫豎屏會改變屏幕寬度值,所以為了保持更小的值除更大的值. if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { //豎屏 devicePercent = (float) deviceWidth / (float) deviceHeight; //豎屏狀態下寬度小與高度,求比 }else { //橫屏 devicePercent = (float) deviceHeight / (float) deviceWidth; //橫屏狀態下高度小與寬度,求比 } if (videoWidth > videoHeight){ //判斷視頻的寬大於高,那么我們就優先滿足視頻的寬度鋪滿屏幕的寬度,然后在按比例求出合適比例的高度 videoWidth = deviceWidth;//將視頻寬度等於設備寬度,讓視頻的寬鋪滿屏幕 videoHeight = (int)(deviceWidth*devicePercent);//設置了視頻寬度后,在按比例算出視頻高度 }else { //判斷視頻的高大於寬,那么我們就優先滿足視頻的高度鋪滿屏幕的高度,然后在按比例求出合適比例的寬度 if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {//豎屏 videoHeight = deviceHeight; /** * 接受在寬度的輕微拉伸來滿足視頻鋪滿屏幕的優化 */ float videoPercent = (float) videoWidth / (float) videoHeight;//求視頻比例 注意是寬除高 與 上面的devicePercent 保持一致 float differenceValue = Math.abs(videoPercent - devicePercent);//相減求絕對值 L.e("devicePercent="+devicePercent); L.e("videoPercent="+videoPercent); L.e("differenceValue="+differenceValue); if (differenceValue < 0.3){ //如果小於0.3比例,那么就放棄按比例計算寬度直接使用屏幕寬度 videoWidth = deviceWidth; }else { videoWidth = (int)(videoWidth/devicePercent);//注意這里是用視頻寬度來除 } }else { //橫屏 videoHeight = deviceHeight; videoWidth = (int)(deviceHeight*devicePercent); } } ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mVideoPlaySurfaceview.getLayoutParams(); layoutParams.width = videoWidth; layoutParams.height = videoHeight; layoutParams.verticalBias = 0.5f; layoutParams.horizontalBias = 0.5f; mVideoPlaySurfaceview.setLayoutParams(layoutParams); }
最后調用這個方法的地方
mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() { //尺寸變化回調 @Override public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { Log.e(TAG, "onVideoSizeChanged: 觸發 width=" + width + "height=" + height); changeVideoSize(); } });
求最正方形算法
其實這個算法不是我的,但是一開始看到的這個別人的算法的時候,突然發現這算法跟我相機預覽求正方形有異曲同工之妙(基本原理就是高寬比除寬高,或者寬高比除高寬,兩個不同的邊相除或者相乘會得到近似正方形的尺寸).但是個人覺得,並不合適在視頻播放的時候使用,因為在橫屏情況下會將視頻變得很小.但是搬過來也是一個參考:
public void changeVideoSize() { int videoWidth = mediaPlayer.getVideoWidth(); int videoHeight = mediaPlayer.getVideoHeight(); //根據視頻尺寸去計算->視頻可以在sufaceView中放大的最大倍數。 float max; if (getResources().getConfiguration().orientation==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { //豎屏模式下按視頻寬度計算放大倍數值 max = Math.max((float) videoWidth / (float) surfaceWidth,(float) videoHeight / (float) surfaceHeight); } else{ //橫屏模式下按視頻高度計算放大倍數值 max = Math.max(((float) videoWidth/(float) surfaceHeight),(float) videoHeight/(float) surfaceWidth); } //視頻寬高分別/最大倍數值 計算出放大后的視頻尺寸 videoWidth = (int) Math.ceil((float) videoWidth / max); videoHeight = (int) Math.ceil((float) videoHeight / max); //無法直接設置視頻尺寸,將計算出的視頻尺寸設置到surfaceView 讓視頻自動填充。 surfaceView.setLayoutParams(new RelativeLayout.LayoutParams(videoWidth, videoHeight)); } @Override public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { changeVideoSize(); }