使用 appcompat-v7 在 Android 中视频播放器熄灯模式

Posted

技术标签:

【中文标题】使用 appcompat-v7 在 Android 中视频播放器熄灯模式【英文标题】:Video player lights out mode in Android using appcompat-v7 【发布时间】:2015-01-07 03:58:05 【问题描述】:

我正在将代码库从本地 Holo(Theme.Holo 等)移植到 appcompat-v7Theme.AppCompat 等)。如果您不想阅读详细信息,最后一部分包含 tl;dr


问题

一切正常,但我在复制一种使用旧 ActionBar 很容易实现的行为时遇到了问题。我有一个视频播放器,在横向上我希望它的行为类似于 YouTube:隐藏(动画)播放器控件、应用栏和状态栏。在用户交互时,UI 控件应离开此“熄灯”模式并返回正常状态。如果用户在 X 秒内没有触摸屏幕,计时器将返回熄灯模式。与 ActionBar 一起工作的相同代码对 Toolbar 不起作用。

所以,我使用的是:

不透明的状态栏 setSystemUiVisibility() 使用以下组合之一: 默认:View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 熄灯:View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE minSdkVersion 是 16 显示和隐藏我简单地调用了show()hide()的ActionBar 为了在应用栏上实现相同的行为,我将Toolbar 子类化并添加了一个show() 和一个hide() 方法,它们做同样的事情(首先简单地使用setVisibility(),然后使用动画——得到相同的结果结果)

LAYOUT_STABLE 使 appbar 最终位于状态栏后面,当然(因为它暗示了 fitSystemWindows。因为 appbar 是视图层次结构中的普通视图,而不是像ActionBar 是,它受那个标志的影响。这是我在屏幕上看到的:

没有立即清楚工具栏的边界是什么,因为应用栏在黑暗中是黑暗的,但您可以看到标题被剪切并且“未对齐”。这是因为工具栏的大小正确但位于状态栏后面。我的主要问题是当时没有公共 API 来获取状态栏高度、矩形或其他任何东西来垂直移动我的应用栏以显示在状态栏下方。

测试主要是在 N5 上的 LPX13D(撰写本文时最新的 Lollipop 公共版本)上进行的,但在 android 4.4 上也可以看到同样的情况。


hacky 解决方案

也就是说,经过相当长一段时间和一些失败的尝试以一种不太老套的方式工作(包括我自己尝试将其放入装饰中的相当绝望的尝试),我采用了这种令人讨厌的方式让它工作:

    onResume: 一种。打电话给setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE),即使我通常不会这样做(风景) 湾。注册OnPreDrawListener

    OnPreDrawListener: 一种。使用View root = getRootView().findViewById(R.id.my_root)获取根视图 湾。获取根视图高度:int rootTop = getAbsoluteViewTop(root)(见下文) C。使用该顶部(将其作为状态栏高度)作为应用栏的 paddingTop d。设置我通常使用的 SystemUiVisibility (LAYOUT_STABLE 等) e.抑制绘图通道

    在下一个绘图过程中,取消注册OnPreDrawListener

这是getAbsoluteViewTop() 方法:

private int getAbsoluteViewTop(View view) 
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    return location[LOCATION_Y];


tl;博士和问题

tl;dr:除非使用 hacky hack,否则无法使用 Toolbar 进行适当的“熄灯”模式。

问题:有没有一种官方且干净的方式来使用Toolbar 实现这种熄灯模式? 我在文档中找不到任何内容。状态栏无法访问(并且您可以在 SO 上找到其大小的所有方法都已损坏,仅供参考)。但也许我错过了一些东西。我很想摆脱这种黑客攻击。

【问题讨论】:

Ander Webb 在 G+ 上建议可以将容器子类化(在我的情况下为 FrameLayout),并覆盖 fitsSystemWindows() 以获取系统栏大小。我必须看看这是否适用于setSystemUiVisibility(LAYOUT_STABLE);如果是这样,我会更新问题/添加答案。 更新 我终于设法获得了一个 PoC 解决方案,它使用了 Chris Banes 的SystemUiHelperfitSystemWindows 和 appcompat-v7(经过调整的版本) r21 的Toolbar。它比我预期的要难,但它确实有效,而且看起来不那么骇人听闻。一旦我有时间清理代码,我就计划开源该 PoC。 我遇到了同样的问题...您是否已经在某处发布了您的代码,或者您介意分享它吗?谢谢! 【参考方案1】:

我发现fitssystemwindows 非常不可靠,当您希望视图层次结构的某些元素全屏显示并且某些元素位于状态栏或操作栏下方时。但我从未见过状态栏后面的操作栏。工具栏是否设置为活动操作栏?你在用Window.FEATURE_ACTION_BAR_OVERLAY吗?无论如何,如果您只需要在onResume() 中为paddingTop 获取一些像素,那么执行以下操作而不是使用OnPreDrawListeners 可能会更干净(尽管仍然很老套)。

class MyVideoActivity extends Activity 
    Toolbar bar;

    //...

    @Override protected void onResume() 
        super.onResume();
        bar.setPaddingTop(getStatusBarHeight());
    

    int getStatusBarHeight() 
        int result = 0;
        Resources res = getResources();
        int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) 
            result = res.getDimensionPixelSize(resourceId);
        
        return result;
    

【讨论】:

是的,我有 setSupportActionBar(toolbar),不,操作栏没有设置为覆盖(我没有 ActionBar,因为我使用的是 AppCompat 主题和工具栏)。您获得状态栏高度的方法是您发现漂浮在 SO 上的方法之一,并且 不起作用。第一个示例:三星对其状态栏使用不同的维度,该维度与您建议使用的(私有且没有任何公共合同)维度具有不同的值。所以...不是一个有效的解决方案,抱歉。【参考方案2】:

不确定这是否会有所帮助,但您是否考虑过使用

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

在您的视频活动的 onCreate 方法中?这可能是一个很好的起点。这基本上隐藏了状态栏并使我的视频全屏显示。

这是我也使用的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_
              android:layout_
              android:background="@color/black">

        <VideoView
            android:id="@id/videoSurface"
            android:layout_
            android:layout_
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:layout_centerInParent="true"
            android:layout_alignParentTop="true"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_gravity="center"
            />

</RelativeLayout>

我知道有些参数是多余的,但最终它给了我想要的效果。这对您来说可能是一个很好的起点?

【讨论】:

以上是关于使用 appcompat-v7 在 Android 中视频播放器熄灯模式的主要内容,如果未能解决你的问题,请参考以下文章

android studio怎么导入appcompat-v7

android studio怎么导入appcompat-v7

Android:无法解决:com.android.support:appcompat-v7:28.1.1

无法在 Android Studio 新项目中解析 com.android.support:appcompat-v7:26.1.0

android studio怎么导入appcompat-v7

无法解决:com.android.support:appcompat-v7:26.0.0