主要解决自定义SurfaceView时,屏幕发生旋转后,SurfaceView也会跟随旋转的问题(因为是做播放器,所以SurfaceView宽高需要由视频宽高决定),最后SurfaceView还需要等比例缩放成屏幕的宽高。
int mWidth = getMeasuredWidth();
int mHeight = getMeasuredHeight();
int oldAngle = 90;
/**
* 旋转更新(屏幕旋转时调用,0和180 -> 横屏,90和270 -> 竖屏)
* 屏幕旋转需要考虑旋转后的高宽变化,例如:竖屏时,高比宽大,横屏时:高比宽小。
* 所以旋转后要确定那边为宽,那边为高,然后将视频等比例缩放至屏幕相应大小。
* @param angle 旋转角度。传入0、180、90、270
*/
private void updateOrientation(int angle) {
if( videoWidth <= 0 || videoHeight <= 0 ) return;
//需要改变宽高的LayoutParams
ViewGroup.LayoutParams lp = getLayoutParams();
//是否为横版视频
boolean isLandscapeVideo = videoWidth > videoHeight;
//是否为横屏
boolean isLandscapeScreen = angle == 0 || angle == 180;
/* 因为横竖屏原因,高宽会发生改变,所以需要取最值来判断高宽 */
int max = mWidth < mHeight ? mHeight : mWidth;
int min = mWidth > mHeight ? mHeight : mWidth;
//-1为平放状态
if( angle == -1 ) angle = oldAngle;
/* 屏幕旋转一共四种结果:竖屏横视频、竖屏竖视频、横屏横视频、横屏竖视频
* 其次,这是经过一段很长的代码精简而来,请不要尝试去理解这些代码。
* 大概意思是横竖屏时判断当前视频的横竖,对高宽进行等比缩放 */
if( (isLandscapeVideo && isLandscapeScreen) || (!isLandscapeVideo && !isLandscapeScreen) ) {
/* 横屏横视频 和 竖屏竖视频 */
lp.width = Utils.calcAspectRatio(
videoWidth, videoHeight, isLandscapeScreen ? min : max, false
);
if( lp.width > ( isLandscapeScreen ? max : min ) ) {
lp.height = Utils.calcAspectRatio(
videoWidth, videoHeight, isLandscapeScreen ? max : min, true
);
lp.width = isLandscapeScreen ? max : min;
}else {
lp.height = isLandscapeScreen ? min : max;
}
}else {
/* 竖屏横视频 和 横屏竖视频 */
lp.width = min + Utils.calcAspectRatio(videoHeight, videoWidth, min, isLandscapeScreen);
lp.height = isLandscapeScreen ? min : lp.width - min;
lp.width = isLandscapeScreen ? lp.width - min : min;
}
setLayoutParams( lp );
if( angle != -1 ) oldAngle = angle;
}
上述代码中的 calcAspectRatio 方法传送门:计算分辨率长宽比