ActionBar 覆盖来自 YouTube 播放器的 YouTubePlayerSupportFragment API
ActionBar overlaying YouTubePlayerSupportFragment from YouTube Player API
我有一个 activity 扩展 AppCompatActivity
,使用扩展 Theme.AppCompat.Light.DarkActionBar
的主题。
此 activity 的视图是 LinearLayout
的 VERTICAL
方向,包含以下视图:
一个 FrameLayout
包含一个 YouTubePlayerSupportFragment
。请注意,我在初始化成功时对获得的 YouTubePlayer
调用以下方法:
setPlayerStyle(PlayerStyle.CHROMELESS)
addFullscreenControlFlag(YouTubePlayer.FULLSCREEN_FLAG_CUSTOM_LAYOUT)
我还在播放器视图上设置了一个 onClickListener
,应该根据需要隐藏和显示 ActionBar
。
包含视频详细信息和内容的另一个视图
- 一些底视图
请注意 activity 调用 supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY)
并且 LinearLayout
的顶部填充为 android.support.v7.appcompat.R.attr.actionBarSize
。
在 AndroidManifest.xml
中,activity 设置了 android:configChanges="orientation|screenSize"
。
在 activity 的 onConfigurationChanged
方法中,我正在检查屏幕方向。如果是横向,我就"going fullscreen",如果是纵向,我就回到正常布局。
"going fullscreen",我的意思是:
- 将视图 n°2 和视图 n°3
visibility
设置为 View.GONE
- 将 activity 的
supportActionBar
背景颜色设置为透明颜色,例如 0x55000000
- 正在将
getWindow().getDecorView().systemUiVisibility
设置为 View.SYSTEM_UI_FLAG_FULLSCREEN
- 更改视图 n°1
LayoutParams
,同时将 width
和 height
设置为 MATCH_PARENT
- 在
YouTubePlayer
上调用 setFullscreen(true)
现在,当我在我的应用程序中时,一切都在纵向模式下工作:视频播放,播放器正确放置在 ActionBar
下方。当进入横向模式时,它继续按预期工作:除了播放器(甚至 ActionBar
),一切都消失了。然后我点击现在全屏的 YouTube 播放器。
预期的结果是 ActionBar
出现,不会中断播放。
实际结果是系统状态栏和ActionBar都出现了,播放中断,报如下错误:
YouTube video playback stopped due to unauthorized overlay on top of player. The YouTubePlayerView is obscured by android.support.v7.widget.ActionBarContainer{43744840 V.ED.... ........ 0,50-1280,162 #7f0d005b app:id/action_bar_container}. The view is inside the YouTubePlayerView, with the distance in px between each edge of the obscuring view and the YouTubePlayerView being: left: 0, top: 50, right: 0, bottom: 558..
YouTubePlayer 应该让 ActionBar 覆盖它,如 Overlay ActionBar Demo found in the Sample Applications 所示。那么这里的问题是什么?我以为它只是检查覆盖它的视图是否是一个 ActionBar,所以我不明白这个确切的错误是怎么可能的!
好的,因为确实不支持 Android YouTube 播放器 API,我将回答您实际上必须如何操作才能正常工作。
首先,放弃使用 ActionBar 的想法。这是一个旧的 API,里面有控件很难看,处理起来很痛苦,而且 甚至不起作用 如果你不使用由Google。这个答案的其余部分将解释如何在 YouTube 播放器上添加控件的工作方法,但是如果你真的想使用 ActionBar,你不会在这里找到答案(据我所知也没有其他地方)。
很好。现在,为了使其正常工作,您可以正常使用 YouTube 播放器。我建议使用片段,因为必须扩展现有的 Activity class 可能是个问题。在 OnInitializationSuccess
回调中使用 player.setPlayerStyle(PlayerStyle.CHROMELESS)
删除播放器的所有控件。
现在,要让您的控件在 Player 之上而不暂停,您需要使用 DialogFragment
(单独使用 Dialog
可能有效,但再次使用 Fragment 带来更多控制你可以做什么):
- 创建您自己的
DialogFragment
子class
- 覆盖
onCreate(Bundle)
并调用 setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Translucent_NoTitleBar)
- 覆盖
onCreateView(LayoutInflater, ViewGroup, Bundle)
并根据需要在此处重新创建 Activity 布局。我正在使用 Kotlin 和 Anko,所以一切对我来说都是动态的,我没有 XML。无论如何,重新创建布局但没有最终视图(结果应该完全不可见)。
- 现在,在替换播放器的视图中,假设您使用了
FrameLayout
,您可以像播放器的 FrameLayout
一样添加控件
覆盖 onStart()
并在现在创建的 Dialog
上调用以下方法,以确保您的对话框是全屏和透明的:
Dialog dialog = getDialog();
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// TODO Dismiss the Dialog AND call onBackPressed() on the underlying Activity
return true;
} else {
return false;
}
}
});
Window window = getWindow();
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.setDimAmount(0f);
layoutParams.setFlags(layoutParams.getFlags() | WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.setAttributes(layoutParams);
现在你必须处理你的控件,让它们在计时器后消失,等等。
只需确保将覆盖播放器的所有内容放在对话框(片段)内的某个位置即可。
我不确定我在这里列出的所有内容都是强制性的,但我就是这样做的,而且效果很好。
注意:正如我所说,我正在使用 Kotlin 和 Anko,我已经有几个月没有写 Java 了,所以这里提供的任何代码都可能有小错别字。如果您看到任何错误,请告诉我。
奖金:我如何处理全屏。
为了处理全屏模式,我只是将 Dialog
中除了播放器和匹配视图(对我来说是 FrameLayout
)之外的所有内容的可见性设置为 GONE
,make确保 LayoutParams
' 这两个视图的宽度和高度设置为 MATCH_PARENT
。要退出全屏,只需将您更改回的所有视图的可见性设置回 VISIBLE
。
我有一个 activity 扩展 AppCompatActivity
,使用扩展 Theme.AppCompat.Light.DarkActionBar
的主题。
此 activity 的视图是 LinearLayout
的 VERTICAL
方向,包含以下视图:
一个
FrameLayout
包含一个YouTubePlayerSupportFragment
。请注意,我在初始化成功时对获得的YouTubePlayer
调用以下方法:setPlayerStyle(PlayerStyle.CHROMELESS) addFullscreenControlFlag(YouTubePlayer.FULLSCREEN_FLAG_CUSTOM_LAYOUT)
我还在播放器视图上设置了一个
onClickListener
,应该根据需要隐藏和显示ActionBar
。包含视频详细信息和内容的另一个视图
- 一些底视图
请注意 activity 调用 supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY)
并且 LinearLayout
的顶部填充为 android.support.v7.appcompat.R.attr.actionBarSize
。
在 AndroidManifest.xml
中,activity 设置了 android:configChanges="orientation|screenSize"
。
在 activity 的 onConfigurationChanged
方法中,我正在检查屏幕方向。如果是横向,我就"going fullscreen",如果是纵向,我就回到正常布局。
"going fullscreen",我的意思是:
- 将视图 n°2 和视图 n°3
visibility
设置为View.GONE
- 将 activity 的
supportActionBar
背景颜色设置为透明颜色,例如0x55000000
- 正在将
getWindow().getDecorView().systemUiVisibility
设置为View.SYSTEM_UI_FLAG_FULLSCREEN
- 更改视图 n°1
LayoutParams
,同时将width
和height
设置为MATCH_PARENT
- 在
YouTubePlayer
上调用
setFullscreen(true)
现在,当我在我的应用程序中时,一切都在纵向模式下工作:视频播放,播放器正确放置在 ActionBar
下方。当进入横向模式时,它继续按预期工作:除了播放器(甚至 ActionBar
),一切都消失了。然后我点击现在全屏的 YouTube 播放器。
预期的结果是 ActionBar
出现,不会中断播放。
实际结果是系统状态栏和ActionBar都出现了,播放中断,报如下错误:
YouTube video playback stopped due to unauthorized overlay on top of player. The YouTubePlayerView is obscured by android.support.v7.widget.ActionBarContainer{43744840 V.ED.... ........ 0,50-1280,162 #7f0d005b app:id/action_bar_container}. The view is inside the YouTubePlayerView, with the distance in px between each edge of the obscuring view and the YouTubePlayerView being: left: 0, top: 50, right: 0, bottom: 558..
YouTubePlayer 应该让 ActionBar 覆盖它,如 Overlay ActionBar Demo found in the Sample Applications 所示。那么这里的问题是什么?我以为它只是检查覆盖它的视图是否是一个 ActionBar,所以我不明白这个确切的错误是怎么可能的!
好的,因为确实不支持 Android YouTube 播放器 API,我将回答您实际上必须如何操作才能正常工作。
首先,放弃使用 ActionBar 的想法。这是一个旧的 API,里面有控件很难看,处理起来很痛苦,而且 甚至不起作用 如果你不使用由Google。这个答案的其余部分将解释如何在 YouTube 播放器上添加控件的工作方法,但是如果你真的想使用 ActionBar,你不会在这里找到答案(据我所知也没有其他地方)。
很好。现在,为了使其正常工作,您可以正常使用 YouTube 播放器。我建议使用片段,因为必须扩展现有的 Activity class 可能是个问题。在 OnInitializationSuccess
回调中使用 player.setPlayerStyle(PlayerStyle.CHROMELESS)
删除播放器的所有控件。
现在,要让您的控件在 Player 之上而不暂停,您需要使用 DialogFragment
(单独使用 Dialog
可能有效,但再次使用 Fragment 带来更多控制你可以做什么):
- 创建您自己的
DialogFragment
子class
- 覆盖
onCreate(Bundle)
并调用setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Translucent_NoTitleBar)
- 覆盖
onCreateView(LayoutInflater, ViewGroup, Bundle)
并根据需要在此处重新创建 Activity 布局。我正在使用 Kotlin 和 Anko,所以一切对我来说都是动态的,我没有 XML。无论如何,重新创建布局但没有最终视图(结果应该完全不可见)。 - 现在,在替换播放器的视图中,假设您使用了
FrameLayout
,您可以像播放器的FrameLayout
一样添加控件
覆盖
onStart()
并在现在创建的Dialog
上调用以下方法,以确保您的对话框是全屏和透明的:Dialog dialog = getDialog(); dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); dialog.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { // TODO Dismiss the Dialog AND call onBackPressed() on the underlying Activity return true; } else { return false; } } }); Window window = getWindow(); window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); WindowManager.LayoutParams layoutParams = window.getAttributes(); layoutParams.setDimAmount(0f); layoutParams.setFlags(layoutParams.getFlags() | WindowManager.LayoutParams.FLAG_DIM_BEHIND); window.setAttributes(layoutParams);
现在你必须处理你的控件,让它们在计时器后消失,等等。 只需确保将覆盖播放器的所有内容放在对话框(片段)内的某个位置即可。
我不确定我在这里列出的所有内容都是强制性的,但我就是这样做的,而且效果很好。
注意:正如我所说,我正在使用 Kotlin 和 Anko,我已经有几个月没有写 Java 了,所以这里提供的任何代码都可能有小错别字。如果您看到任何错误,请告诉我。
奖金:我如何处理全屏。
为了处理全屏模式,我只是将 Dialog
中除了播放器和匹配视图(对我来说是 FrameLayout
)之外的所有内容的可见性设置为 GONE
,make确保 LayoutParams
' 这两个视图的宽度和高度设置为 MATCH_PARENT
。要退出全屏,只需将您更改回的所有视图的可见性设置回 VISIBLE
。