网友通过本文主要向大家介绍了videoview全屏播放,videoview设置全屏,videoview全屏,videoview全屏切换,videoview等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
用原生VideoView进行全屏播放时的问题,videoview全屏播放
之前参加了一个课程,里面有一节讲到了用视频作为启动界面。讲师用的是自定义VideoView,重写onMeasure方法,因为原生的VideoView在那情况下不能实现全屏播放。当时没有深入研究,现在补回来。
用的是36氪之前的视频(608×1080)和Genymotion中的Google Nexus 5(1080×1920)。
一、效果图
1、原生VideoView的效果,这里没有让底部的导航栏也变透明。因为截图上来很难看到差别,后面会解释。
xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <VideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="false" android:focusable="false" android:focusableInTouchMode="false"/> </LinearLayout>
java
public class VideoViewActivity extends AppCompatActivity { private VideoView mVideoView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_view); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } mVideoView = (VideoView) findViewById(R.id.video_view); mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.kr36)); mVideoView.start(); mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mVideoView.start(); } }); } }
2、自定义的VideoView
布局文件基本同上,除了控件名和id
... <com.example.test.test_fitstatusbar.CustomVideoView android:id="@+id/custom_video_view"
...
Activity.java也是基本同上。这里是自定义VideoView的java代码,只重写了onMeasure方法。
public class CustomVideoView extends VideoView { public CustomVideoView(Context context) { super(context); } public CustomVideoView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomVideoView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = getDefaultSize(0, widthMeasureSpec); int height = getDefaultSize(0, heightMeasureSpec); setMeasuredDimension(width, height); } }
二、在对比原生VideoView的onMeasure方法之前,先了解一些事情。
1、这里涉及到MeasureSpec类,这个类代码不多,但很精妙。我也有很多地方没弄懂。不过在这里,只需了解它的三种mode就可以了。
/** * 1、UNSPECIFIED * 根据源码的注释,其大概意思是parent不对child做出限制.它想要什么size就给什么size.看了一些教程,都说用得很少,或者是系统内部才用得上.所以先不管了 * 2、EXACTLY * 对应于match_parent和给出具体的数值 * 3、AT_MOST * 对应于wrap_content */ public static class MeasureSpec { private static final int MODE_SHIFT = 30; private static final int MODE_MASK = 0x3 << MODE_SHIFT; public static final int UNSPECIFIED = 0 << MODE_SHIFT; public static final int EXACTLY = 1 << MODE_SHIFT; public static final int AT_MOST = 2 << MODE_SHIFT;
......
public static int getMode(int measureSpec) { return (measureSpec & MODE_MASK); }
public static int getSize(int measureSpec) { return (measureSpec & ~MODE_MASK); }
......
}
而这里,我所有控件的width和height都是mach_parent,所以以下分析都是基于MeasureSpec.EXACTLY这个mode。
2、getDefaultSize
public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
因为都是MeasureSpec.EXACTLY,所以最终返回的结果是MeasureSpec.getSize(measureSpec),与size,也就是第一个参数无关。
3、setMeasuredDimension
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { boolean optical = isLayoutModeOptical(this); if (optical != isLayoutModeOptical(mParent)) { Insets insets = getOpticalInsets(); int opticalWidth = insets.left + insets.right; int opticalHeight = insets.top + insets.bottom; me