El reproductor de video apaga el modo en Android usando appcompat-v7

Estoy portando un codebase de Holo nativo ( Theme.Holo etc) a la appcompat-v7 ( Theme.AppCompat y así sucesivamente). La última sección contiene el tl; dr si no desea leer los detalles.


La cuestión

Todo está funcionando, pero tuve problemas para replicar un comportamiento que era bastante fácil de usar con la antigua ActionBar. Tengo un reproductor de video, y en el paisaje quiero que se comporte como YouTube: ocultar (animar) los controles del reproductor, la barra de aplicaciones y la barra de estado. En la interacción del usuario, los controles de interfaz de usuario deberían dejar este modo de "apagado" y volver al estado normal. Un temporizador volvería entonces al modo de luces apagadas si el usuario no toca la pantalla durante X segundos. El mismo código que funcionó con ActionBar no hace el truco con una Toolbar .

Entonces, lo que estoy usando es:

  • Una barra de estado opaca
  • setSystemUiVisibility() utilizando uno de estos combos:
    • Predeterminado: View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    • Se apaga: View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
  • minSdkVersion es 16
  • Para mostrar y ocultar la ActionBar simplemente llamé show() y hide() en ella
  • Para implementar el mismo comportamiento en la barra de aplicaciones I subclase Toolbar y agregó un show() y un método hide() que hacen lo mismo (primero simplemente usando setVisibility() y luego usando animaciones – obteniendo los mismos resultados)

El LAYOUT_STABLE hecho para que la appbar terminaría detrás de la barra de estado, por supuesto (ya que implica un fitSystemWindows . Puesto que la appbar es una vista normal en la jerarquía de la vista y no está en la decoración como la ActionBar era, se ve afectada por Que era lo que estaba viendo en la pantalla:

Barra de aplicaciones detrás de la barra de estado

No inmediatamente claro cuáles son los límites de la barra de herramientas, como la barra de aplicaciones es oscuro en la oscuridad, pero se puede ver el título se corta y "desalineada". Esto se debe a que la barra de herramientas estaba correctamente dimensionada pero detrás de la barra de estado. Mi principal problema fue que no hay API pública para obtener la altura de la barra de estado, rectángulo o cualquier otra cosa para cambiar mi barra de aplicaciones verticalmente para mostrar debajo de la barra de estado.

Las pruebas se realizaron sobre todo en un N5 en LPX13D (la última versión pública de Lollipop en el momento de escribirlo), pero lo mismo se podía ver sucediendo en Android 4.4.


La solución hacky

Dicho esto, después de bastante tiempo y algunos intentos fallidos de hacer que funcione de una manera no demasiado hacky (incluyendo el intento bastante desesperado de tratar de ponerlo en la decoración de mí mismo), recurrí a esta desagradable manera de hacer que funcione :

  1. En onResume :
    a. Llamar setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE) incluso cuando normalmente no lo haría (paisaje)
    segundo. Registrar un OnPreDrawListener

  2. En el OnPreDrawListener :
    a. Obtener la vista raíz con View root = getRootView().findViewById(R.id.my_root)
    segundo. Obtener la altura de la vista raíz: int rootTop = getAbsoluteViewTop(root) (ver más abajo)
    do. Utilice esa parte superior (con la intención de que sea una altura de la barra de estado) como paddingTop para la appbar
    re. Establezca la SystemUiVisibility que normalmente utilizaría ( LAYOUT_STABLE etc)
    mi. Suprimir el pase de dibujo

  3. En la siguiente pasada de dibujo, OnPreDrawListener el registro OnPreDrawListener

Este es el método getAbsoluteViewTop() :

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

Tl; dr y pregunta

Tl; dr : no hay manera de hacer un modo apropiado de "luces apagadas" con una Toolbar menos que hacky hacks se emplean.

Pregunta: ¿hay una manera oficial y limpia de implementar este modo de apagado con la Toolbar ?
No pude encontrar nada en los documentos. La barra de estado no es accesible (y todas las formas de averiguar su tamaño se puede encontrar en SO están rotas, FYI). Pero tal vez estoy perdiendo algo. Me encantaría deshacerme de este hack.

He encontrado fitssystemwindows muy poco fiable, así como cuando desea que algunos elementos de la jerarquía de vista para ser de pantalla completa y algunos elementos para estar por debajo de la barra de estado o barra de acción. Pero nunca he visto la barra de acción detrás de la barra de estado. ¿La barra de herramientas está configurada como la barra de acción de la actividad? ¿Está utilizando Window.FEATURE_ACTION_BAR_OVERLAY ? De todos modos, si todo lo que necesitas es obtener un número de píxeles para el paddingTop en onResume() , podría ser un poco más limpio (todavía hacky aunque) para hacer algo como lo siguiente en lugar de utilizar 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; } } 

No estoy seguro de si esto le ayudará, pero lo ha mirado usando

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

En el método onCreate de tu actividad de video? Podría ser un buen punto de partida. Esto básicamente oculta la barra de estado y hace que mi vídeo a pantalla completa.

Este es el diseño que también uso:

 <?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> 

Sé que algunos de los parámetros son redundantes, pero al final me da el efecto deseado que quería. ¿Podría ser un buen punto de partida para usted?

  • Cambiar URI de MediaPlayer
  • Android lo que hace exactamente error mediaplayer 1, -107
  • Detener y iniciar música en las llamadas entrantes
  • Android - MediaPlayer + PowerManager.PARTIAL_WAKE_LOCK
  • No hay sonido procedente de Android Emulator
  • Android Media Grabación utilizando hilos
  • Android, Cómo mostrar el buffering% de onBufferingUpdate
  • MediaPlayer se detiene y se reinicia
  • Android - Cómo saber cuándo MediaPlayer está almacenando en búfer
  • Controlar el volumen en MediaPlayer
  • Reproducción de archivos .wav cortos - Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.