Подтвердить что ты не робот

Видеопроигрыватель отключает режим в Android, используя appcompat-v7

Я переношу кодовую базу из родного Холо (Theme.Holo и т.д.) в appcompat-v7 (Theme.AppCompat и т.д.). В последнем разделе содержится tl; dr, если вы не хотите читать детали.


Проблема

Все работало, но у меня были проблемы, реплицировавшие одно поведение, которое было довольно легко использовать с помощью старого ActionBar. У меня есть видеоплеер, и в ландшафте я хочу, чтобы он вел себя как YouTube: скрыть (анимировать) элементы управления проигрывателем, панель приложений и строку состояния. При взаимодействии с пользователем элементы управления пользовательского интерфейса должны оставить этот режим "выключен" и вернуться в нормальное состояние. Затем таймер перейдет в режим отключения света, если пользователь не коснется экрана в течение X секунд. Тот же код, который работал с ActionBar, не выполняет трюк с Toolbar.

Итак, я использую:

  • Прозрачная строка состояния
  • setSystemUiVisibility() используя одну из этих комбо:
    • default: 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
  • чтобы показать и скрыть ActionBar, я просто назвал show() и hide() на нем
  • реализовать такое же поведение на панели приложения я подкласса Toolbar и добавить метод show() и hide(), который делает то же самое (сначала просто используя setVisibility(), а затем используя анимацию - получение того же результаты)

LAYOUT_STABLE сделал так, что панель приложения окажется в конце строки состояния, конечно (поскольку это подразумевает fitSystemWindows. Так как панель приложения является обычным представлением в иерархии представлений и не находится в декоре, например, ActionBar был, на него повлиял этот флаг. Это было то, что я видел на экране:

App bar behind the status bar

Непонятно, какие границы панели инструментов есть, так как панель приложения темна на темноте, но вы можете видеть, что заголовок разрезан и "смещен". Это связано с тем, что панель инструментов была правильно установлена, но за панель состояния. Моя основная проблема заключалась в том, что нет публичного API, чтобы получить высоту строки состояния, прямоугольник или что-то еще, чтобы сдвинуть панель приложения по вертикали, чтобы показать ниже строки состояния.

Тестирование проводилось в основном на N5 на LPX13D (последняя публичная сборка Lollipop на момент написания), но то же самое можно было увидеть на Android 4.4.


Хакерное решение

Тем не менее, после довольно долгого времени и некоторых неудачных попыток заставить его работать не слишком-взломанным способом (включая довольно отчаянную попытку самим поместить его в декор), я прибегал к этому мерзкому способу заставляя его работать:

  • В onResume:
    а. Вызовите setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE), даже если я обычно этого не делал (пейзаж)
    б. Зарегистрируйте OnPreDrawListener

  • В OnPreDrawListener:
    а. Получить представление корня с помощью View root = getRootView().findViewById(R.id.my_root)
    б. Получить высоту корневого представления: int rootTop = getAbsoluteViewTop(root) (см. Ниже)
    с. Используйте этот верх (намереваясь его как высоту строки состояния) в качестве paddingTop для панели приложений
    д. Установите SystemUiVisibility, который я обычно использую (LAYOUT_STABLE и т.д.)
    е. Подавить прохождение чертежа

  • В следующем проходе чертежа отмените регистрацию OnPreDrawListener

Это метод getAbsoluteViewTop():

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

tl; dr и вопрос

tl; dr: нет способа сделать правильный режим "выключен" с помощью Toolbar, если не используются хакерские хаки.

Вопрос: есть ли официальный и чистый способ реализовать этот режим подсветки с помощью Toolbar?
Я не мог найти ничего в документах. Строка состояния недоступна (и все способы узнать ее размер, который вы можете найти на SO, сломаны, FYI). Но, может быть, я что-то упустил. Я хотел бы избавиться от этого взлома.

4b9b3361

Ответ 1

Я нашел fitssystemwindows довольно ненадежным, когда вы хотите, чтобы некоторые элементы иерархии представлений были полноэкранными, а некоторые элементы были ниже строки состояния или панели действий. Но я никогда не видел панель действий за панель состояния. Является ли панель инструментов установленной как панель действий? Используете ли вы Window.FEATURE_ACTION_BAR_OVERLAY? В любом случае, если вам нужно получить несколько пикселей для paddingTop в onResume(), это может быть немного чище (хотя и взломанно), чтобы сделать что-то вроде следующего, а не использовать OnPreDrawListener s.

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;
    }
}

Ответ 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_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="@color/black">

        <VideoView
            android:id="@id/videoSurface"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            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>

Я знаю, что некоторые из параметров являются избыточными, но в конце он дает мне желаемый эффект, который я хотел. Это может быть хорошей отправной точкой для вас?