如何使用ExoPlayer在横屏模式下全屏播放视频

19

我正在使用exoplayer在我的Android应用程序中播放来自URL的视频。 在纵向模式下,一切都按预期工作(在活动中使用viewpager,片段和选项卡)。 我的目标是当用户处于横向模式时,在全屏中播放视频。 这意味着仅视频将在横向模式下播放,并且所有其他详细信息将消失,并在纵向模式下返回到原始布局。 请问如何实现这一点?或者实现这一点的最佳方法是什么?任何示例代码都将不胜感激。

Video to be play when portrait


3
如果您已经找到了问题的解决方案,请发布并接受它作为答案。这将有助于其他人。 - Sandeep Yohans
9个回答

12

我是一个新手,所以这是我能提供的最好帮助。顺便说一句,在 Exoplayer Demo 应用程序中进行了测试,我将 exoplayer 的高度更改为 600 像素,并应用了这段代码,它完美地运行。

添加此代码以检测屏幕方向

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);

  // Checking the orientation of the screen
  if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
     //First Hide other objects (listview or recyclerview), better hide them using Gone.
     FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) simpleExoPlayerView.getLayoutParams();
     params.width=params.MATCH_PARENT;
     params.height=params.MATCH_PARENT;
     simpleExoPlayerView.setLayoutParams(params);
  } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
     //unhide your objects here.
     FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) simpleExoPlayerView.getLayoutParams();
     params.width=params.MATCH_PARENT;
     params.height=600;
     simpleExoPlayerView.setLayoutParams(params);
  }
}

顺便说一句,如果您没有使用FrameLayout而是使用RelativeLayout

      RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) simpleExoPlayerView.getLayoutParams();

我忘记了你需要隐藏操作或标题栏,希望这段代码能够帮到你。将这些代码添加到上面的代码中,同时我认为你需要扩展你的活动到AppCompatActivity,让getSupportActionBar代码起作用。

if(getSupportActionBar()!=null) {
   getSupportActionBar().hide();
}
//To show the action bar
if(getSupportActionBar()!=null) {
   getSupportActionBar().show();
 }

此外,这可能有助于将整个项目设置为全屏,隐藏状态栏等等,必须根据屏幕方向在onConfigurationChanged中添加。

在横向模式下

ExoPlayerActivity.this.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN || View.SYSTEM_UI_FLAG_IMMERSIVE);

退出 PORTRAIT 模式下的全屏

ExoPlayerActivity.this.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

我编辑了代码,添加了View.SYSTEM_UI_FLAG_IMMERSIVE以防止在用户点击视频控制按钮时状态栏显示。


2
非常感谢您的回答。但最终我找到了这个使用对话框解决我的问题的 Github 项目 https://github.com/GeoffLedak/ExoplayerFullscreen。 - Jean-Pascal MEWENEMESSE
2
使用您的解决方案的关键是在清单文件中还要设置android:configChanges="orientation|screenSize|keyboardHidden" - schneida
1
这是真的,在ExoPlayer项目中默认已经存在,因此我认为任何导入ExoPlayer到自己的项目中的人都会将ExoPlayer清单中的设置复制并粘贴到自己的项目清单中,并且还会导入隐藏操作栏等内容。以下是ExoPlayer清单中的内容:android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" - Daiwik Dan
我认为这是一个非常好的解决方案:它完全将旋转的“处理”交给了安卓系统,将exoplayer实例视为“简单”的视图。您不必担心exoplayer实例的生命周期。感谢您分享它。 - Andrea De Gaetano

2

在设置播放器时,您可以检查方向并相应地设置参数:

if (getActivity().getResources().getConfiguration().orientation == 
Configuration.ORIENTATION_LANDSCAPE) {
        params = (LinearLayout.LayoutParams) 
exoPlayerView.getLayoutParams();
        params.width = params.MATCH_PARENT;
        params.height = params.MATCH_PARENT;
        exoPlayerView.setLayoutParams(params);
    }

隐藏操作栏:

((AppCompatActivity) getActivity()).getSupportActionBar().hide();

这似乎适用于具有硬件按钮的设备,但对于屏幕上有虚拟按钮的设备,它实际上并没有充满整个屏幕。(顶部的按钮和状态栏仍然显示) - Mr.Drew

2

My solution with data binding:

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>
    <import type="android.view.View" />
    <variable
        name="orientationLandscape"
        type="boolean" />

    <variable
        name="step"
        type="com.udacity.zeban.baking.data.models.Step" />
</data>

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.exoplayer2.ui.SimpleExoPlayerView
        android:id="@+id/step_video"
        android:layout_width="match_parent"
        android:layout_height="@dimen/player_height"
        app:layout_constraintBottom_toTopOf="@+id/scroll"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_height="@{orientationLandscape}" />

    <ScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/step_video">

        <android.support.v7.widget.CardView
            android:id="@+id/description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/spacing_small"
            android:visibility="@{orientationLandscape ? View.GONE : View.VISIBLE}">

            <TextView
                android:id="@+id/step_description"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/spacing_small"
                android:text="@{step.getDescription()}"
                tools:text="@tools:sample/lorem/random" />

        </android.support.v7.widget.CardView>
    </ScrollView>
</android.support.constraint.ConstraintLayout>

在您的活动或片段中添加以下内容:

@BindingAdapter("layout_height")
public static void setLayoutHeight(View view, boolean orientationLandscape) {
    view.getLayoutParams().height = orientationLandscape ? RelativeLayout.LayoutParams.MATCH_PARENT : 600;
}

@Override
public void onResume() {
    super.onResume();
    binding.setOrientationLandscape(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
}

我的项目在这里


1
缺少项目链接。 - Sandeep Yohans

2
你可以为横屏模式创建一个对话框,首先要初始化一个对话框。 原始答案是"最初的回答"。
private void initFullscreenDialog() {
    mFullScreenDialog = new Dialog(mContext, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
        public void onBackPressed() {
            if (mExoPlayerFullscreen) {    //mExoPlayerFullscreen is a boolean to check if it is already fullscreen or not
                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();
            }
        }
    });

最初的回答:你可以按照以下方式打开和关闭全屏模式:

然后您可以按照以下方式打开和关闭全屏:

private void openFullscreenDialog() {
    ((ViewGroup) playerView.getParent()).removeView(playerView);
    mFullScreenDialog.addContentView(playerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    mFullScreenIcon.setImageResource(R.drawable.ic_exit_fullscreen);
    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.setImageResource(R.drawable.ic_fullscreen);
}

我在xml中使用FrameLayout作为PlayerView的父级,如下所示:

最初的回答:

<FrameLayout
        android:id="@+id/main_media_frame2"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_below="@+id/common_item_header_container"
        android:background="#000000">

        <com.google.android.exoplayer2.ui.PlayerView
            android:id="@+id/player_view"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:focusable="true"></com.google.android.exoplayer2.ui.PlayerView>
    </FrameLayout>

1
请解释得更详细一些,((FrameLayout) findViewById(R.id.main_media_frame)).addView(playerView); 是哪个 FrameLayout? - Mahmoud Mabrok
谢谢,现在我不能在Kotlin中使用这个代码:public void onBackPressed() { if (mExoPlayerFullscreen) { //mExoPlayerFullscreen是一个布尔值,用于检查是否已经全屏 closeFullscreenDialog(); } super.onBackPressed(); } - Mahmoud Mabrok
onBackPressed已被重写。我认为onBackPressed()不应该有任何问题。 - Abhishek Kumar
请您添加使用Kotlin编写的对话框代码版本,谢谢。 - Mahmoud Mabrok
当我将其设置为匹配父级,并从全屏视图返回时,使用wrap_content参数视频不适合全屏显示。 - Mahmoud Mabrok

1
请确保在横屏模式下,将播放器视图的长度和宽度设置为与其父视图相匹配。
  1. 使用以下代码隐藏状态栏: getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

  2. 使用以下代码隐藏导航栏: getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);


1

对于有硬件按钮的屏幕,如果没有其他视图与ExoPlayer的PlayerView共享屏幕,则默认情况下它将填充整个屏幕。但是对于屏幕上有虚拟按钮的设备,它将不会填充整个屏幕。在我的情况下,通过将此行添加到PlayerView中解决了问题。

ads:resize_mode="fill"

由于我的活动布局中有AdMob广告,因此我在顶部的RelativeLayout标签中添加了这行代码。

xmlns:ads="http://schemas.android.com/apk/res-auto"

我知道这看起来没有意义,但是使用android:resize_mode="fill"会导致gradle构建错误。
还可以删除系统UI以获得更多空间:
    @Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        hideSystemUI();
    }
}

private void hideSystemUI() {
    // Enables  "lean back" mode
    // Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(
            // Hide the nav bar and status bar
            View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN);

}

欲了解更多信息,请访问Android开发者页面https://developer.android.com/training/system-ui/immersive


3
android:resize_mode="fill"会出现错误,因为它不是Android属性,而是自定义组件的属性。你可以使用除android之外的任何内容。 - Raj Suvariya
我使用了app:resize_mode="fill",但在竖屏模式下显示为拉伸的竖屏屏幕。横屏模式下工作正常,但竖屏模式下不行,有什么想法吗? - Gyan Swaroop Awasthi

0

我认为我们在这里错过了更明显的答案。只需在 layout-land 目录中创建一个新的布局文件,以便在横向模式下应用新的布局文件。

在这个新的布局文件中,只需要将你的 ExoPlayerlayout_height 改为 match_parent,这样它就会占据整个屏幕。


我们如何使用另一个XML文件来适配横屏模式? - Gyan Swaroop Awasthi

0

设置屏幕方向的最简单方法。
取一个布尔值:

boolean abc = false;

现在:

if (abc) {
    list.set(position, new IconsModel(R.drawable.screenlocked, "Portrait"));
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    abc = false;
} else {
    list.set(position, new IconsModel(R.drawable.screenrotate, "Landscape"));
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    abc = true;
}

我正在使用 recyclerview,所以我使用了 list.add
你可以使用这行代码代替:

imageView.setImageDrawable(getResources().getDrawable(R.drawable.yourIamge));

-8

我在playerView中添加了:

app:resize_mode="fixed_width"

然后一切都运作良好


它能工作,但会隐藏或裁剪底部屏幕,有什么解决办法吗?我使用了app:resize_mode="fill",但在纵向模式下会显示拉伸的纵向屏幕。 - Gyan Swaroop Awasthi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接