Actualicé la versión de la API de destino del proyecto a 30 y ahora veo que la propiedad systemUiVisibility está obsoleta.
El siguiente código de kotlin es el que estoy usando, que en realidad es equivalente al método setSystemUiVisibility en Java.
playerView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) Avíseme si tiene algún reemplazo estable para este código obsoleto. La recomendación de Google es usar WindowInsetsController , pero no sé cómo hacerlo.
Espero que te ayude.
Anteriormente, al implementar la navegación de borde a borde o el modo inmersivo, uno de los primeros pasos a seguir era usar las banderas systemUiVisibility para solicitar que la aplicación se muestre en pantalla completa. Esta nueva versión de Android desaprueba este campo y para diseñe la aplicación a pantalla completa, debe usar un nuevo método en la clase Window : setDecorFitsSystemWindows pasando false como argumento como se muestra a continuación.
window.setDecorFitsSystemWindows(false) Clase WindowInsetsController que le permite hacer cosas que antes se controlaban a través de indicadores systemUiVisibility , como ocultar o mostrar la barra de estado o la barra de navegación (ocultar y mostrar métodos, respectivamente)
Por ejemplo, puede mostrar y ocultar fácilmente el teclado como se muestra a continuación:
// You have to wait for the view to be attached to the // window (otherwise, windowInsetController will be null) view.doOnLayout { view.windowInsetsController?.show(WindowInsets.Type.ime()) // You can also access it from Window window.insetsController?.show(WindowInsets.Type.ime()) }A partir de la versión 1.5.0-alpha02 , androidx.core tiene WindowCompat.setDecorFitsSystemWindows()
Para habilitar borde a borde:
WindowCompat.setDecorFitsSystemWindows(window, false)Fragmento de TL;DR
Se necesita envolver en la estructura if-else para evitar java.lang.NoSuchMethodError: No virtual method setDecorFitsSystemWindows en versiones anteriores de SDK.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.setDecorFitsSystemWindows(false) } else { window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN }Enlaces con información completa sobre inserciones y modos de pantalla completa en Android 11
https://blog.stylingandroid.com/android11-windowinsets-part1/
También es posible que desee tener una barra de estado translúcida y puede hacerlo simplemente configurando un estilo para el tema de su aplicación de la siguiente manera:
<style name="App.MyTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <item name="android:windowLightStatusBar">true</item> </style>Se puede mostrar un mensaje de pelusa (dependiendo de su nivel de API mínimo actual): android:windowLightStatusBar requiere el nivel de API 23 (el mínimo actual es 21) , por lo que debe anular este tema en estilos v23
Para compatibilidad, use WindowCompat y WindowInsetsControllerCompat . Deberá actualizar su dependencia de gradle para androidx.core a al menos 1.6.0-alpha03 para que haya soporte para setSystemBarsBehavior en SDK < 30.
private fun hideSystemUI() { WindowCompat.setDecorFitsSystemWindows(window, false) WindowInsetsControllerCompat(window, mainContainer).let { controller -> controller.hide(WindowInsetsCompat.Type.systemBars()) controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } private fun showSystemUI() { WindowCompat.setDecorFitsSystemWindows(window, true) WindowInsetsControllerCompat(window, mainContainer).show(WindowInsetsCompat.Type.systemBars()) } Puede encontrar más información sobre WindowInsets viendo este video de YouTube
Para dispositivos con muescas en la parte superior de la pantalla, puede agregar lo siguiente a su archivo v27 theme.xml para que la interfaz de usuario aparezca a ambos lados de la muesca:
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>Puede leer más en este enlace: Recorte de pantalla
Si alguien busca la versión de Java.
Para Activity :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { getWindow().setDecorFitsSystemWindows(false); if (getWindow().getInsetsController() != null) { getWindow().getInsetsController().hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); getWindow().getInsetsController().setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); } } else { getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } para FragmentDialog y AlertDialog :
if (getDialog() != null && getDialog().getWindow() != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { getDialog().getWindow().setDecorFitsSystemWindows(false); } else { if (getActivity() != null) { getDialog().getWindow().getDecorView().setSystemUiVisibility(getActivity().getWindow().getDecorView().getSystemUiVisibility()); } } }Según Chris Banes @ Android Developers, el canal oficial de YouTube usa el siguiente código
class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var view: View override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) view = binding.root setContentView(view) } override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) if (hasFocus) hideSystemUI() } private fun hideSystemUI() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // Tell the window that we want to handle/fit any system windows WindowCompat.setDecorFitsSystemWindows(window, false) val controller = view.windowInsetsController // Hide the keyboard (IME) controller?.hide(WindowInsets.Type.ime()) // Sticky Immersive is now ... controller?.systemBarsBehavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // When we want to hide the system bars controller?.hide(WindowInsets.Type.systemBars()) /*val flag = WindowInsets.Type.statusBars() WindowInsets.Type.navigationBars() WindowInsets.Type.captionBar() window?.insetsController?.hide(flag)*/ } else { //noinspection @Suppress("DEPRECATION") // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE. window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY // Set the content to appear under the system bars so that the // content doesn't resize when the system bars hide and show. or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // Hide the nav bar and status bar or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN) } } }Aquí hay un ejemplo de interfaz de usuario de enlace de muestra
Para usuarios de Java (gracias a @James):
//hide system UI Window window = activity.getWindow(); View decorView = activity.getWindow().getDecorView(); WindowCompat.setDecorFitsSystemWindows(window, false); WindowInsetsControllerCompat controllerCompat = new WindowInsetsControllerCompat(window, decorView); controllerCompat.hide(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.navigationBars()); controllerCompat.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); (Editar) Use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE para mostrar solo las barras del sistema temporalmente cuando al deslizar, BEHAVIOR_SHOW_BARS_BY_SWIPE las mostrará permanentemente después de deslizar.
Solución oficial 2022 con código Kotlin:
val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView) ?: return // Configure the behavior of the hidden system bars windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // Hide both the status bar and the navigation bar windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())Fuente: https://developer.android.com/training/system-ui/immersive#kotlin
Para cualquiera que busque hacer esto en Xamarin Forms y C#, he agregado este código en la clase MainActivity en el archivo MainActivity.cs:
private void SetWindowLayout() { if (Window != null) { if (Build.VERSION.SdkInt >= BuildVersionCodes.R) { IWindowInsetsController wicController = Window.InsetsController; Window.SetDecorFitsSystemWindows(false); Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen); if (wicController != null) { wicController.Hide(WindowInsets.Type.Ime ()); wicController.Hide(WindowInsets.Type.NavigationBars()); } } else { #pragma warning disable CS0618 Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen); Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.Fullscreen | SystemUiFlags.HideNavigation | SystemUiFlags.Immersive | SystemUiFlags.ImmersiveSticky | SystemUiFlags.LayoutHideNavigation | SystemUiFlags.LayoutStable | SystemUiFlags.LowProfile); #pragma warning restore CS0618 } } }Luego, en el método anulado OnCreate, haga una llamada a SetWindowLayout()
Luego, invalide el método OnWindowFocusChanged():
public override void OnWindowFocusChanged( Boolean bHasFocus) { base.OnWindowFocusChanged(bHasFocus); if (bHasFocus) SetWindowLayout(); }Espero que esto ayude a todos en Visual Studio.
Loz.
JAVA
private void showSystemUI() { WindowCompat.setDecorFitsSystemWindows(getWindow(), true); new WindowInsetsControllerCompat(getWindow(), yourRootView).show(WindowInsetsCompat.Type.systemBars()); } private void hideSystemUI() { WindowCompat.setDecorFitsSystemWindows(getWindow(), false); WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(getWindow(), yourRootView); controller.hide(WindowInsetsCompat.Type.systemBars()); controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); }use esto: window.setDecorFitsSystemWindows (falso)
Asegúrese de tener una configuración de gradle de compilación de Android que tenga minsdk de 30
En el archivo Estilos agregue dos elementos:
<item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> Y en el archivo de actividad antes de setContentView(R.layout.activity_main) las siguientes líneas:
try { actionBar!!.hide(); } catch (e:Exception){ }Aquí hay una solución sencilla que funciona para todas las versiones de Android y oculta la barra de estado
WindowInsetsControllerCompat(window, window.decorView).hide(WindowInsetsCompat.Type.systemBars())Funciona bien en emuladores, pero a veces en un dispositivo real, si aparece el teclado, la barra de estado se vuelve a mostrar. Si realmente no necesita ocultar/mostrar la barra de estado mediante programación, simplemente agregue la ventana a pantalla completa como un elemento del tema que usará para esa pantalla. Por ejemplo, puede crear un estilo en theme.xml
<style name="HideStatusBar" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/purple_500</item> <item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorOnPrimary">@color/white</item> <!-- hides status bar--> <item name="android:windowFullscreen">true</item> </style>y en AndroidManifest.xml agrega un estilo a esa sección de actividad
<activity android:name=".MainActivity" android:screenOrientation="portrait" <!-- The style--> android:theme="@style/NoactionBar" android:exported="true" />Esto también funciona para todas las versiones.
Si usa Jetpack Compose , use este método en setContent :
@Composable fun HideSystemUi() { val systemUiController = rememberSystemUiController() SideEffect { systemUiController.isSystemBarsVisible = false } } No olvide agregar esto al archivo build.gradle de su aplicación (ajuste la versión si es necesario):
implementation "com.google.accompanist:accompanist-systemuicontroller:0.17.0"La documentación se puede encontrar aquí , aunque es posible que desee echar un vistazo a las fuentes .