横竖屏切换SurfaceView 大小的调整
视频播放的实现大概有以下形式:
1.使用系统自带视频播放类VideoView
2.使用MediaPlayer+surfaceView
3.使用一些第三方框架如:vitamio 还有像新浪在github上开放的视频播放框架等...
使用场景:
第一种方法:简单,但是VideoView不支持自定义视频,也就是你只能使用系统给你提供的布局,这在很大时候是不符合我们项目需求的。
第二种方法:使用MediaPlayer+surfaceView的话支持我们自定义布局,使用起来稍微复杂,这种方法存在的一个缺点就是只是支持MP4 3gp这样的视频编码格式,其他格式的视频均不能播放。
第三种方法:使用第三方框架,不用多说,照着SDK来就行了,相对也简单,同时支持更多的播放格式,再是目前这样的框架好像收费的居多。
SurfaceView在横竖屏切换情况下应如何调整大小
首先先看效果图:
布局如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.sj.vediodemo.MainActivity"><RelativeLayoutandroid:id="@+id/layout_gesture"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#000"android:gravity="center_horizontal"><SurfaceViewandroid:id="@+id/sv"android:layout_width="match_parent"android:layout_height="match_parent"/></RelativeLayout><Buttonandroid:id="@+id/change"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:onClick="changeOrientation"android:text="横竖屏切换"/>
</RelativeLayout>
很简单,上面一个SurfaceView 下面一个Button 用于横竖屏切换。
在ManiFest.xml 中设置:
<activityandroid:name=".MainActivity1"android:configChanges="keyboard|screenSize|orientation"android:label="@string/app_name"android:screenOrientation="portrait"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity>
设置了一个ScreenOrientation 属性为纵向,同时设置了configChanges 属性,为了防止横竖屏切换导致Activity重新创建。
Main.java 代码:
public class MainActivity1 extends AppCompatActivityimplements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener {public static final float SHOW_SCALE = 16 * 1.0f / 9;private RelativeLayout mSurfaceLayout;private SurfaceView mSurfaceView;private SurfaceHolder mHolder;private MediaPlayer mMediaPlayer;//屏幕宽度private int mScreenWidth;//屏幕高度private int mScreenHeight;//记录现在的播放位置private int mCurrentPos;private boolean isLand;private DisplayMetrics displayMetrics;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main1);displayMetrics = new DisplayMetrics();this.getWindow().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);mScreenWidth = displayMetrics.widthPixels;mScreenHeight = displayMetrics.heightPixels;//后台异常终止,应当恢复原有位置播放if (savedInstanceState != null)mCurrentPos = savedInstanceState.getInt("currentPos", 0);initView();}private void initView() {mSurfaceLayout = (RelativeLayout) findViewById(R.id.layout_gesture);RelativeLayout.LayoutParams lp =(RelativeLayout.LayoutParams) mSurfaceLayout.getLayoutParams();lp.height = (int) (mScreenWidth * SHOW_SCALE);mSurfaceLayout.setLayoutParams(lp);mSurfaceView = (SurfaceView) findViewById(R.id.sv);mHolder = mSurfaceView.getHolder();mHolder.addCallback(this);}private void resetSize() {float areaWH = 0.0f;int height;if (!isLand) {// 竖屏16:9height = (int) (mScreenWidth / SHOW_SCALE);areaWH = SHOW_SCALE;} else {//横屏按照手机屏幕宽高计算比例height = mScreenHeight;areaWH = mScreenWidth / mScreenHeight;}RelativeLayout.LayoutParams layoutParams =new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);mSurfaceLayout.setLayoutParams(layoutParams);int mediaWidth = mMediaPlayer.getVideoWidth();int mediaHeight = mMediaPlayer.getVideoHeight();float mediaWH = mediaWidth * 1.0f / mediaHeight;RelativeLayout.LayoutParams layoutParamsSV = null;if (areaWH > mediaWH) {//直接放会矮胖int svWidth = (int) (height * mediaWH);layoutParamsSV = new RelativeLayout.LayoutParams(svWidth, height);layoutParamsSV.addRule(RelativeLayout.CENTER_IN_PARENT);mSurfaceView.setLayoutParams(layoutParamsSV);}if (areaWH < mediaWH) {//直接放会瘦高。int svHeight = (int) (mScreenWidth / mediaWH);layoutParamsSV = new RelativeLayout.LayoutParams(mScreenWidth, svHeight);layoutParamsSV.addRule(RelativeLayout.CENTER_IN_PARENT);mSurfaceView.setLayoutParams(layoutParamsSV);}}private void initMediaPlayer() {if (mMediaPlayer != null) {//从Home 返回mMediaPlayer.setDisplay(mHolder);mMediaPlayer.start();} else {mMediaPlayer = new MediaPlayer(); //销毁返回重新初始化try {mMediaPlayer.setDataSource(this, Uri.parse(MediaPath.MEDIA_HENG));mMediaPlayer.setLooping(true);mMediaPlayer.setDisplay(mHolder);mMediaPlayer.setOnPreparedListener(this);mMediaPlayer.prepareAsync();mMediaPlayer.setScreenOnWhilePlaying(true);} catch (IOException e) {e.printStackTrace();}}}//只有在点击Home键或者程序发生异常时才会执行此方法@Overrideprotected void onSaveInstanceState(Bundle outState) {outState.putInt("currentPos", mCurrentPos);super.onSaveInstanceState(outState);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {//SV可见initMediaPlayer();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {//SV状态变化}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {if (mMediaPlayer != null) {mMediaPlayer.pause();mCurrentPos = mMediaPlayer.getCurrentPosition();}}/*** 销毁掉MediaPlayer对象*/private void releaseMP() {if (mMediaPlayer != null) {mMediaPlayer.stop();mMediaPlayer.release();mMediaPlayer = null;System.gc();}}@Overridepublic void onPrepared(MediaPlayer mp) {resetSize();if (mCurrentPos != 0) {mMediaPlayer.seekTo(mCurrentPos);}mMediaPlayer.start();}@Overridepublic void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);isLand = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);mScreenWidth = displayMetrics.widthPixels;mScreenHeight = displayMetrics.heightPixels;resetSize();}public void changeOrientation(View view) {if (Configuration.ORIENTATION_LANDSCAPE == this.getResources().getConfiguration().orientation) {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);} else {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);}}@Overridepublic void onWindowFocusChanged(boolean hasFocus) {super.onWindowFocusChanged(hasFocus);if (hasFocus && Build.VERSION.SDK_INT >= 19) {View decorView = getWindow().getDecorView();decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_FULLSCREEN| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}}@Overrideprotected void onDestroy() {super.onDestroy();releaseMP();}
}
因为主要是讲解SurfaceView大小的调整问题,所以并没有去定制控制MediaPlayer的UI布局,简单的分析一下代码:
先来看initView()方法:
1. 目前纵向视频播放一般接受的尺寸为16:9,所以在这我也是设置了16:9的尺寸,视频的宽(RelativeLayout的宽)为手机的宽,视频高的话,根据比例换算。
2.SurfaceView的产生和销毁,都是通过SurfaceHolder进行控制的,添加上SurfaceView的监听事件,这个的话原因想必大家也都知道,一旦Activity切换到后台或者跳转到其他的Activity界面,SurfaceView 就会被销毁,当切换回来Activity界面的时候SurfaceView 又会自动创建,这个时候我们需要重新绑定上新的SurfaceHolder,不然就会出现只是播放声音而不播放画面的问题,代码中每次执行SurfaceCreate()都会执行initMediaPlayer()这个方法,在这个方法中重新绑定了一次SurfaceHoder.
3.播放完毕或者是停止都需要将MediaPlayer资源释放掉。
Ok,主要来 分析一下resetSize()这个方法:
resetSize()这个方法,没别在onPrepare()和onConfigurationChanged中调用到了,一个是视频准备完成,另外一个是横竖屏切换。
53行:
if (!isLand) {// 竖屏16:9height = (int) (mScreenWidth / SHOW_SCALE);areaWH = SHOW_SCALE;
} else {//横屏按照手机屏幕宽高计算比例height = mScreenHeight;areaWH = mScreenWidth / mScreenHeight;
}
isLand 是否横屏,不是的话根据16:9比例计算出视频框高,是横屏的话,则手机屏幕的高作为视频框的高,比例当然是视频的宽/高,需要注意的是手机横竖屏切换会导致屏幕的宽高颠倒,在onConfigChanged()中已重新获取了手机宽高。
获取视频大小的宽高比
同时按照视频的宽高比进行等比例缩放即可。如果是播放区的宽高比小于视频的宽高比的话,这个时候说明视频的宽高更大一些,我们需要将播放框的宽作为视
频的宽,然后按照等比例缩放计算出视频的高度。计算出宽高之后SurfaceView重新布局即可。SurfaceView 布局在RleativeLayout中设置了居中对其.
如果是播放区域宽高比大于视频宽高比的话,这个时候的情况就是视频的高要大一些,那么需要缩放到视频播放框以内,也就是让视频的高等于播放区的高度,
if (areaWH > mediaWH) {//直接放会矮胖int svWidth = (int) (height * mediaWH);layoutParamsSV = new RelativeLayout.LayoutParams(svWidth, height);layoutParamsSV.addRule(RelativeLayout.CENTER_IN_PARENT);mSurfaceView.setLayoutParams(layoutParamsSV);
}if (areaWH < mediaWH) {//直接放会瘦高。int svHeight = (int) (mScreenWidth / mediaWH);layoutParamsSV = new RelativeLayout.LayoutParams(mScreenWidth, svHeight);layoutParamsSV.addRule(RelativeLayout.CENTER_IN_PARENT);mSurfaceView.setLayoutParams(layoutParamsSV);
}
int mediaWidth = mMediaPlayer.getVideoWidth();
int mediaHeight = mMediaPlayer.getVideoHeight();float mediaWH = mediaWidth * 1.0f / mediaHeight;
横竖屏切换SurfaceView 大小的调整相关推荐
- Genymotion横竖屏切换及调节分辨率大小
由于本人之前用的都是Windows7.Windows8的操作系统,用的是Genymotion模拟器,所以一直都没有出现模拟器屏幕是横向的问题.刚刚买回来的电脑是Windows10的操作系统,安装gen ...
- android播放器竖屏,SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,
MNVideoPlayer SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,手势快进快退.调节音量,亮度等.之前也发布过一个视频播放列表, 项目截图: 使用步骤: ...
- Android视频播放器横竖屏切换时遇到的问题记录
我用的播放器是KMedia,一个开源的播放器,链接如下 https://github.com/BlackQi/KMedia 我个人觉得还是很好用的,支持定制.现在遇到一个问题就是播放时横屏铺满全屏视频 ...
- 解决Android手机 屏幕横竖屏切换
Android中当屏幕横竖屏切换时,Activity的生命周期是重新加载(说明当前的Activity给销毁了,但又重新执行加载),怎么使屏幕横竖屏切换时,当前的Activity不销毁呢? 1. 在An ...
- android activity横竖屏切换,Activity重新创建问题解决!
activityA和B A跳转到B 1:在主配置文件中添加Bactivity,如果不想B在横竖屏切换的时候导致activity的销毁和重新创建;可在声明activity中添加 android:conf ...
- Android横竖屏切换View设置不同尺寸或等比例缩放的自定义View的onMeasure解决方案(2)...
Android横竖屏切换View设置不同尺寸或等比例缩放的自定义View的onMeasure解决方案(2) 附录文章1以xml布局文件方式实现了一个view在横竖屏切换时候的大小尺寸缩放,实现这种需求 ...
- cocos2d-x游戏开发屏幕横竖屏切换
android解决方案: 1.在游戏的主activity中编写一个静态方法(继承Cocos2dxActivity) public static void changedActivityOrientat ...
- WebView网页视频统一全屏播放及横竖屏切换
WebView 支持 Html5 video 进行全屏播放及横竖屏自动切换 1.检查AndroidManifest.xml清单文件,WebView控件所在的Activity配置信息;检查Activit ...
- Android 横竖屏切换
2019独角兽企业重金招聘Python工程师标准>>> Android开发中,大多APP可能根据实际情况直接将APP的界面方向设死了,或竖屏或横屏.但是,我们还是会遇到横竖屏切换的功 ...
最新文章
- 如何保证缓存和数据库的双写的一致性
- qt combox 向上弹出_一睹芳容!人类首次拍到活的公羊角乌贼 手臂和触须向上飞速穿过水柱...
- Centos 磁盘管理及配额管理
- oracle dblink 验证,Oracle DBLINK 简单使用
- python实战——发邮件
- spark executor task执行
- 第七章:在Spark集群上使用文件中的数据加载成为graph并进行操作(3)
- 学了这几招,社交时人人都对你刮目相看(转载)
- 为什么大部分人会碌碌无为?
- 马化腾“闪退”华人首富;马云回应收购中天微;华为遭美刑事调查 | CSDN极客头条...
- [导入]Replace函数vbTextCompare不支持日文韩文
- 【Shell】获取文件名和扩展名
- c#生成token访问的接口_python测试开发django60.token登录(TokenAuthentication)
- java aws批量_通过 S3 Batch Operations (批量操作)功能轻松处理海量对象
- linux安装java步骤
- 如何在 Ubuntu 上转换图像、音频和视频格式
- PHP语言基本数据类型
- 《3D数学基础》1.7 向量的向量积
- “创新雷神号”卫星成功发射,华为云分布式云原生“天地一体”首次组网成功
- 虚拟化、云计算与超融合的简单总结