Android悬浮窗口

您所在的位置:网站首页 画中画功能app Android悬浮窗口

Android悬浮窗口

2024-06-04 15:47| 来源: 网络整理| 查看: 265

效果展示

 

前言

从 Android 8.0(API 级别 26)开始,Android 允许活动以画中画 (PiP) 模式启动。PiP 是一种特殊类型的多窗口模式,主要用于视频播放。它允许用户在固定在屏幕一角的小窗口中观看视频,同时在应用程序之间导航或浏览主屏幕上的内容。 PiP 利用 Android 7.0 中提供的多窗口 API 来提供固定的视频叠加窗口。要将 PiP 添加到您的应用程序,您需要注册支持 PiP 的 Activity,根据需要将您的 Activity 切换到 PiP 模式,并确保 UI 元素被隐藏并且当 Activity 处于 PiP 模式时视频播放继续。 PiP 窗口出现在屏幕的最顶层,位于系统选择的角落。

用户如何与画中画窗口交互

用户可以将画中画窗口拖到另一个位置。从 Android 12 开始,用户还可以:

单击窗口可显示全屏切换、关闭按钮、设置按钮和应用程序提供的自定义操作(例如,播放控件)。 双击窗口可在当前 PiP 大小和最大 PiP 大小之间切换。通过将窗口拖动到左边缘或右边缘来隐藏窗口;要取消隐藏窗口,请点击隐藏窗口的可见部分或将其拖出。 使用捏合缩放调整画中画窗口的大小。

应用控制当前活动何时进入画中画模式。这里有些例子:

当用户点击主页按钮(在按钮导航模式下)或向上滑动到主页(在手势导航模式下)时,活动可以进入画中画模式。(这就是 Google 地图在用户同时运行另一个活动时继续显示方向的方式。) 当用户从视频返回浏览其他内容时,您的应用可以将视频移至画中画模式。 当用户观看一集内容的结尾时,您的应用可以将视频切换到画中画模式。主屏幕显示有关该系列下一集的宣传或摘要信息。 应用程序可以为用户提供一种在观看视频时排队其他内容的方式。视频继续以画中画模式播放,而主屏幕显示内容选择活动。

声明画中画支持

默认情况下,系统不会自动支持应用程序的画中画。如果想在应用程序中支持画中画,请在清单中注册视频活动,方法是设置 android:supportsPictureInPicture为true. 此外,指定 Activity 处理布局配置更改,以便在 PiP 模式转换期间发生布局更改时 Activity 不会重新启动。

将您的活动切换为画中画

要进入画中画模式,活动必须调用 enterPictureInPictureMode(). 例如,当用户单击应用程序 UI 中的专用按钮时,以下代码会将Activity切换到画中画模式:

private void minimize() { // Calculate the aspect ratio of the PiP screen. PictureInPictureParams.Builder mPictureInPictureParamsBuilder = new PictureInPictureParams.Builder(); Rational aspectRatio = new Rational(binding.videoView.getWidth(), binding.videoView.getHeight()); mPictureInPictureParamsBuilder.setAspectRatio(aspectRatio).build(); enterPictureInPictureMode(mPictureInPictureParamsBuilder.build()); }

如果希望包含将活动切换到画中画模式而不是进入后台的逻辑。例如,如果用户在应用程序导航时按下主页或最近按钮,谷歌地图就会切换到画中画模式。可以通过覆盖来捕获这种情况 onUserLeaveHint():

@Override public void onUserLeaveHint () { if (iWantToBeInPipModeNow()) { enterPictureInPictureMode(); } }

从 Android 12 开始,您可以使用该 setAutoEnterEnabled 标志在手势导航模式下向上滑动到主页时提供更流畅的画中画模式转换。

要实现此功能:

        1.用于setAutoEnterEnabled构造PictureInPictureParams.Builder,如下:

setPictureInPictureParams(new PictureInPictureParams.Builder()     .setAspectRatio(aspectRatio)     .setSourceRectHint(sourceRectHint)     .setAutoEnterEnabled(true)     .build());

        2.setPictureInPictureParams最新 PictureInPictureParams消息。应用不应等待 onUserLeaveHint回调(就像在 Android 11 中所做的那样)。例如,setPictureInPictureParams如果宽高比发生变化,应用程序可能希望在第一次播放和任何后续播放时调用。

        3.setAutoEnterEnabled(false)根据需要调用。例如,如果当前播放处于暂停状态,则视频应用进入 PiP 可能不是最佳选择。

画中画期间处理 UI

当activity进入或退出画中画模式时,系统调用 Activity.onPictureInPictureModeChanged() 或Fragment.onPictureInPictureModeChanged()。应该重写这些回调以重绘活动的 UI 元素。在画中画模式下,活动会显示在一个小窗口中,应用程序处于画中画模式时,用户无法与应用程序的 UI 元素进行交互,并且可能难以看到小的 UI 元素的详细信息。具有最少 UI 的视频播放活动可提供最佳用户体验。如果应用需要为画中画提供自定义操作,请参阅本文档中的添加控件。在 Activity 进入 PiP 之前移除其他 UI 元素,并在您的 Activity 再次变为全屏时恢复它们:

@Override public void onPictureInPictureModeChanged( boolean isInPictureInPictureMode, Configuration configuration) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, configuration); } 退出画中画模式时支持更流畅的动画

从 Android 12 开始,该SourceRectHint 标志现在被重复使用以在退出画中画模式时实现更流畅的动画。退出时,系统使用当前可用的动画创建动画 sourceRectHint,无论是Rect用于进入画中画的原始动画还是Rect应用程序提供的更新动画。

要实现此功能,请按如下方式:

1.继续构建PictureInPictureParams和以sourceRectHint 获得aspectRatio 平滑的进入动画。

2.如有必要,请sourceRectHint 在系统开始退出转换之前更新。当系统即将退出画中画模式时,活动的视图层次结构将布置到其目标配置(例如,全屏)。应用程序可以将布局更改侦听器附加到其根视图或目标视图(例如视频播放器视图)以检测事件并在动画开始之前更新 sourceRectHint。

// Listener is called right after the user exits PiP but before // animating. playerView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { if (left != oldLeft || right != oldRight || top != oldTop || bottom != oldBottom) { // The playerView’s bounds changed, update the source hint rect to // reflect its new bounds. final Rect sourceRectHint = new Rect(); playerView.getGlobalVisibleRect(sourceRectHint); setPictureInPictureParams( new PictureInPictureParams.Builder() .setSourceRectHint(sourceRectHint) .build()); } }); 添加控件

当用户打开窗口的菜单时,画中画窗口可以显示控件(通过在移动设备上点击窗口,或从电视遥控器中选择菜单。)

如果一个应用程序有一个活动的媒体会话,那么将出现播放、暂停、下一个和上一个控件。

还可以在进入 PiP 模式之前通过 build PictureInPictureParams with显式指定自定义操作PictureInPictureParams.Builder.setActions() ,并在进入 PiP 模式时使用 enterPictureInPictureMode(android.app.PictureInPictureParams) or传递参数setPictureInPictureParams(android.app.PictureInPictureParams)。不能超过最大数getMaxNumPictureInPictureActions()

禁用非视频内容的无缝调整大小

Android 12 添加了setSeamlessResizeEnabled 标志,当在画中画窗口中调整非视频内容的大小时,它提供了更加平滑的淡入淡出动画。以前,在画中画窗口中调整非视频内容的大小可能会产生不和谐的视觉伪影。

该setSeamlessResizeEnabled标志true默认设置为向后兼容。将此设置保留为true用于视频内容,并将其更改为false用于非视频内容。

要禁用非视频内容的无缝调整大小:

setPictureInPictureParams(new PictureInPictureParams.Builder() .setSeamlessResizeEnabled(false) .build()); 在画中画中继续播放视频

当活动切换到画中画时,系统会将活动置于暂停状态并调用活动的 onPause()方法。如果活动在画中画模式下暂停,则不应暂停视频播放,并且应继续播放。

在 Android 7.0 及更高版本中,当系统调用 Activity onStop()和 onStart(). 通过这样做,可以避免在 onPause() 中检查应用是否处于画中画模式并显式继续播放。

如果必须在onPause()实现中暂停播放,请通过适当地调用和处理播放来检查画中画模式isInPictureInPictureMode(),例如:

@Override public void onPause() { // If called while in PiP mode, do not pause playback if (isInPictureInPictureMode()) { // Continue playback ... } else { // Use existing playback logic for paused Activity behavior. ... } }

当活动从画中画模式切换回全屏模式时,系统会恢复活动并调用 onResume()方法。

使用单个播放活动进行画中画

在应用程序中,用户可能会在主屏幕上浏览内容时选择新视频,而视频播放活动处于画中画模式。以全屏模式在现有播放活动中播放新视频,而不是启动可能会使用户感到困惑的新活动。

为确保单个活动用于视频播放请求并根据需要切换到或退出画中画模式,请在清单中将活动设置 android:launchMode为singleTask

{ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { minimize(); } }); initData(); } private void initData() { MediaController mediaController = new MediaController(this); binding.videoView.setMediaController(mediaController); mediaController.setMediaPlayer(binding.videoView); binding.videoView.setVideoPath("https://stream7.iqilu.com/10339/upload_transcode/202002/18/20200218114723HDu3hhxqIT.mp4"); binding.videoView.start(); } @RequiresApi(api = Build.VERSION_CODES.O) private void minimize() { // Calculate the aspect ratio of the PiP screen. PictureInPictureParams.Builder mPictureInPictureParamsBuilder = new PictureInPictureParams.Builder(); Rational aspectRatio = new Rational(binding.videoView.getWidth(), binding.videoView.getHeight()); mPictureInPictureParamsBuilder.setAspectRatio(aspectRatio).build(); enterPictureInPictureMode(mPictureInPictureParamsBuilder.build()); } @Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); adjustFullScreen(newConfig); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { adjustFullScreen(getResources().getConfiguration()); } } private void adjustFullScreen(Configuration config) { final WindowInsetsControllerCompat insetsController = ViewCompat.getWindowInsetsController(getWindow().getDecorView()); if (insetsController == null) return; if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { insetsController.hide(WindowInsetsCompat.Type.systemBars()); binding.button.setVisibility(View.GONE); } else { insetsController.show(WindowInsetsCompat.Type.systemBars()); binding.button.setVisibility(View.VISIBLE); } } @Override public void onPictureInPictureModeChanged( boolean isInPictureInPictureMode, Configuration configuration) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, configuration); } @Override protected void onDestroy() { super.onDestroy(); binding.videoView.stopPlayback(); } }

xml布局

PS:acvitiy的style设置成无actionBar的

清单文件中这样添加:



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3