我尝试在RecyclerView和ViewPager中使用exoplayer显示节目视频(.mp4)。我用自定义布局显示视频控制器。到现在为止还挺好。
现在尝试像其他视频播放器一样全屏显示视频如何使用,但在exoplayer doc中找不到好方法。
谁能帮我?
ExoPlayer库目前不提供启用/禁用全屏模式的内置方法。你需要自己实现这个,或者为此我找到一些第三方代码。
基本上需要两个步骤:
a)将窗口和活动属性设置为全屏和/或沉浸式模式,并(如果需要)更改为横向模式。这并不困难。见this page on Android Developers。
b)过渡渲染到SimpleExoPlayerView
(实际上它是关于Surface),它以沉浸式模式覆盖整个视口。在所有API级别上实现最佳用户体验更具挑战性。
为了获得最佳的用户体验,我们希望在转换到全屏和返回时保持播放器播放,以便无缝继续播放。在RecyclerView中,对于所有API级别来说,这是一个很难解决的问题。
方法1
最简单的方法可能是单独的SimpleExoPlayerView实例,只要您进入沉浸式模式,就会将其置于布局之上(有些人打开一个带有第二个视图的对话框,有些人在布局中只有第二个视图。以某种方式并按需显示/隐藏它。
然后将播放器实例从嵌入在RV中的SimpleExoPlayerView中分离出来,并通过调用static helper method将其附加到全屏视图:
SimpleExoPlayerView.switchTargetView(simpleExoPlayer, oldPlayerView, newPlayerView);
这种方法在API> = 23时非常有效。使用API 23,添加了允许动态交换表面的MediaCodec.setOutputSurface方法。上面的静态方法确保应用此技术。因此,音频和视频继续播放,进入和退出全屏的用户体验非常流畅。对于API <= 22,需要创建一个新的编解码器实例来交换到另一个表面。这会中断播放,并且此方法的用户体验会降低。
方法2
为避免在较低的API级别上交换到另一个表面,您需要使用单个表面并以某种方式将其转换为全屏。您可以隐藏除SimpleExoPlayerView之外的所有内容,并设置布局宽度和高度以匹配其父级,或者您可以使用占位符替换视频视图并将其放在顶部和背面。
对于简单的布局,这可以很好地工作,但是复杂的布局可能包括片段,viewpagers,recyclerviews这可能是一个非常干扰的操作,导致某些东西闪烁或很快中断播放(在某些API级别,例如从视图层次结构中删除播放器视图时) )。我已经看到这很好地适用于各种布局。
进一步的方法/挑战
当您深入挖掘和/或根本不使用SimpleExoPlayerView时,可能还有其他可能更好的方法。
您可以通过设置播放器的参数将播放器设置为全屏。
Params params = (LinearLayout.LayoutParams)
exoPlayerView.getLayoutParams();
params.width=params.MATCH_PARENT;
params.height=params.MATCH_PARENT;
exoPlayerView.setLayoutParams(params);
}
并隐藏操作栏:
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
getActionBar().hide();
希望有所帮助
务必设置播放器视图的长度和宽度以与其父级匹配。
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
这可能为时已晚,但这可能有助于其他开发人员。
默认情况下,Exoplayer不提供全屏功能。所以我们需要一个解决方法。我们可以使用对话框实现此全屏功能。我们只需要从我们的活动中删除并添加Playerview到对话框。
mFullScreenDialog = new Dialog(mContext, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
public void onBackPressed() {
if (mExoPlayerFullscreen) { //mExoPlayerFullscreen is a boolean that we need to maintain to know whether screen is fullscreen or not.
((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
closeFullscreenDialog();
}
super.onBackPressed();
}
};
这里我们初始化了对话框。
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mExoPlayerFullscreen) {
((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
openFullscreenDialog();
} else {
((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
closeFullscreenDialog();
}
}
});
在这里,我们初始化了exoplayer的全屏按钮。
private void openFullscreenDialog() {
((ViewGroup) playerView.getParent()).removeView(playerView);
mFullScreenDialog.addContentView(playerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.exoplayer_shrink));
mExoPlayerFullscreen = true;
mFullScreenDialog.show();
}
private void closeFullscreenDialog() {
((ViewGroup) playerView.getParent()).removeView(playerView);
((FrameLayout) findViewById(R.id.main_media_frame)).addView(playerView);
mExoPlayerFullscreen = false;
mFullScreenDialog.dismiss();
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.exoplayer_expand));
}
playerview是您要初始化的Playerview
<FrameLayout
android:id="@+id/main_media_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"></com.google.android.exoplayer2.ui.PlayerView>
</FrameLayout>
在java中,
playerView = (PlayerView) findViewById(R.id.player_view);