视频播放的实现大概有以下形式:

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 大小的调整相关推荐

  1. Genymotion横竖屏切换及调节分辨率大小

    由于本人之前用的都是Windows7.Windows8的操作系统,用的是Genymotion模拟器,所以一直都没有出现模拟器屏幕是横向的问题.刚刚买回来的电脑是Windows10的操作系统,安装gen ...

  2. android播放器竖屏,SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,

    MNVideoPlayer SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,手势快进快退.调节音量,亮度等.之前也发布过一个视频播放列表, 项目截图: 使用步骤: ...

  3. Android视频播放器横竖屏切换时遇到的问题记录

    我用的播放器是KMedia,一个开源的播放器,链接如下 https://github.com/BlackQi/KMedia 我个人觉得还是很好用的,支持定制.现在遇到一个问题就是播放时横屏铺满全屏视频 ...

  4. 解决Android手机 屏幕横竖屏切换

    Android中当屏幕横竖屏切换时,Activity的生命周期是重新加载(说明当前的Activity给销毁了,但又重新执行加载),怎么使屏幕横竖屏切换时,当前的Activity不销毁呢? 1. 在An ...

  5. android activity横竖屏切换,Activity重新创建问题解决!

    activityA和B A跳转到B 1:在主配置文件中添加Bactivity,如果不想B在横竖屏切换的时候导致activity的销毁和重新创建;可在声明activity中添加 android:conf ...

  6. Android横竖屏切换View设置不同尺寸或等比例缩放的自定义View的onMeasure解决方案(2)...

    Android横竖屏切换View设置不同尺寸或等比例缩放的自定义View的onMeasure解决方案(2) 附录文章1以xml布局文件方式实现了一个view在横竖屏切换时候的大小尺寸缩放,实现这种需求 ...

  7. cocos2d-x游戏开发屏幕横竖屏切换

    android解决方案: 1.在游戏的主activity中编写一个静态方法(继承Cocos2dxActivity) public static void changedActivityOrientat ...

  8. WebView网页视频统一全屏播放及横竖屏切换

    WebView 支持 Html5 video 进行全屏播放及横竖屏自动切换 1.检查AndroidManifest.xml清单文件,WebView控件所在的Activity配置信息;检查Activit ...

  9. Android 横竖屏切换

    2019独角兽企业重金招聘Python工程师标准>>> Android开发中,大多APP可能根据实际情况直接将APP的界面方向设死了,或竖屏或横屏.但是,我们还是会遇到横竖屏切换的功 ...

最新文章

  1. 如何保证缓存和数据库的双写的一致性
  2. qt combox 向上弹出_一睹芳容!人类首次拍到活的公羊角乌贼 手臂和触须向上飞速穿过水柱...
  3. Centos 磁盘管理及配额管理
  4. oracle dblink 验证,Oracle DBLINK 简单使用
  5. python实战——发邮件
  6. spark executor task执行
  7. 第七章:在Spark集群上使用文件中的数据加载成为graph并进行操作(3)
  8. 学了这几招,社交时人人都对你刮目相看(转载)
  9. 为什么大部分人会碌碌无为?
  10. 马化腾“闪退”华人首富;马云回应收购中天微;华为遭美刑事调查 | CSDN极客头条...
  11. [导入]Replace函数vbTextCompare不支持日文韩文
  12. 【Shell】获取文件名和扩展名
  13. c#生成token访问的接口_python测试开发django60.token登录(TokenAuthentication)
  14. java aws批量_通过 S3 Batch Operations (批量操作)功能轻松处理海量对象
  15. linux安装java步骤
  16. 如何在 Ubuntu 上转换图像、音频和视频格式
  17. PHP语言基本数据类型
  18. 《3D数学基础》1.7 向量的向量积
  19. “创新雷神号”卫星成功发射,华为云分布式云原生“天地一体”首次组网成功
  20. 虚拟化、云计算与超融合的简单总结

热门文章

  1. 使用De Morgan法则来理解代码
  2. 【VUE项目实战】1、学习目标以及概述
  3. AntdPro之ProFormDependency
  4. SQLserver修改表名和列名
  5. Python opencv框选视频保存图片
  6. 信号与系统(一):响应的分类和联系(通解、特解,暂态、稳态,零输入、零状态)、稳定性、传递函数
  7. 2021第六届GPLT 团体程序设计天梯赛CCCC 个人题解
  8. mse均方误差计算公式_视觉SLAM十四讲实践之真实轨迹和估计轨迹均方根误差
  9. 用C语言写个字符串一维数组的逆序输出,c语言怎么用数组倒序输出
  10. CMake学习笔记(一)——CMake官网教程