Cómo evitar que el diseño se superponga con la barra de estado de iOS

81

Estoy trabajando en un tutorial para la navegación React Native. Descubrí que todo el diseño comienza a cargarse desde la parte superior de la pantalla en lugar de debajo de la barra de estado. Esto hace que la mayoría de los diseños se superpongan con la barra de estado. Puedo solucionar esto agregando un relleno a la vista al cargarlos. ¿Es esta la forma real de hacerlo? No creo que agregar relleno manualmente sea una forma real de resolverlo. ¿Existe una forma más elegante de solucionar este problema?

import React, { Component } from 'react';
import { View, Text, Navigator } from 'react-native';

export default class MyScene extends Component {
    static get defaultProps() {
            return {
                    title : 'MyScene'    
            };  
    }   
    render() {
            return (
                    <View style={{padding: 20}}> //padding to prevent overlap
                            <Text>Hi! My name is {this.props.title}.</Text>
                    </View> 
            )   
    }    
}

A continuación se muestran las capturas de pantalla antes y después de que se agregue el relleno. ingrese la descripción de la imagen aquí

Acantilado
fuente
13
Buena pregunta, pero quizás puedas recortar las imágenes.
Quv
stackoverflow.com/a/39300715/1540350 <: esta respuesta no solo solucionará el problema mencionado aquí, sino que incluso le dará la posibilidad de colorear el fondo de la barra de estado en iOS y Android.
Martin Braun

Respuestas:

36

Hay una forma muy sencilla de solucionar este problema. Haz un componente.

Puede crear un componente StatusBar y llamarlo primero después del primer contenedor de vista en sus componentes principales.

Aquí está el código para el que uso:

'use strict'
import React, {Component} from 'react';
import {View, Text, StyleSheet, Platform} from 'react-native';

class StatusBarBackground extends Component{
  render(){
    return(
      <View style={[styles.statusBarBackground, this.props.style || {}]}> //This part is just so you can change the color of the status bar from the parents by passing it as a prop
      </View>
    );
  }
}

const styles = StyleSheet.create({
  statusBarBackground: {
    height: (Platform.OS === 'ios') ? 18 : 0, //this is just to test if the platform is iOS to give it a height of 18, else, no height (Android apps have their own status bar)
    backgroundColor: "white",
  }

})

module.exports= StatusBarBackground

Después de hacer esto y exportarlo a su componente principal, llámelo así:

import StatusBarBackground from './YourPath/StatusBarBackground'

export default class MyScene extends Component {
  render(){
    return(
      <View>
        <StatusBarBackground style={{backgroundColor:'midnightblue'}}/>
      </View>
    )
  }
}

 

Luis Rizo
fuente
MidnightBlueno es válido, dicho por React Native: Advertencia: Tipo de accesorio fallido: Prop no válido backgroundColorsuministrado
Raptor
2
Debería serlo midnightblue.
bblincoe
19
La barra de estado de iOS no tiene un tamaño fijo. Puede ser más grande al compartir Wifi o en una llamada.
edA-qa mort-ora-y
1
¿Cómo uso esto cuando uso la conexión de navegación de React con redux? Todas las páginas están en un navegador de pila o navegador de pestañas (anidado) y se conectan con redux
Yasir
5
Si importa el componente nativo de reacción "StatusBar" y luego usa: en height: (Platform.OS === 'ios') ? 20 : StatusBar.currentHeight,lugar de ? 20 : 0,, obtendrá el mismo resultado en Android.
mrroot5
60

Ahora puede usar lo SafeAreaViewque está incluido en React Navigation:

<SafeAreaView>
    ... your content ...
</SafeAreaView>
Greg Ennis
fuente
2
Puede ser bueno tener en cuenta que este componente está incluido react-navigationahora de forma predeterminada.
Aᴄʜᴇʀᴏɴғᴀɪʟ
13
esto no resuelve el problema de la superposición de la barra de estado: empaqueté mi aplicación en SafeAreaView y mi aplicación todavía se superpone a la barra de estado. Parece estar orientado hacia la situación de la muesca / esquinas redondeadas del iPhone X
izikandrw
No envuelve su aplicación en ella, envuelve una pantalla en ella.
Greg Ennis
¡Oh, eso es bueno! Me gusta ese.
Asaf Katz
1
@AndreFigueiredo No es correcto. Funciona bien en todos los dispositivos iPhone, siempre que sea> iOS 11.
Fellow Stranger
17

Intenté una forma más simple para esto.

Podemos obtener la altura de la barra de estado en Android y usar SafeAreaView junto con ella para que el código funcione en ambas plataformas.

import { SafeAreaView, StatusBar, Platform } from 'react-native';

Si cerramos la sesión Platform.OSy StatusBar.currentHeightobtenemos los registros,

console.log('Height on: ', Platform.OS, StatusBar.currentHeight);

Altura en: androide 24 y Altura en: androide 24

Ahora podemos agregar opcionalmente margen / relleno a nuestra vista de contenedor usando

paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0

El código final en App.js está a continuación:

export default class App extends React.Component {
  render() {
    return (
      <SafeAreaView style={{ flex: 1, backgroundColor: "#fff" }}>
        <View style={styles.container}>
          <Text>Hello World</Text>
        </View>
      </SafeAreaView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0
  }
});
Gaurav Saluja
fuente
1
Lo probé en Android y está funcionando. Todavía no puedo probarlo en iOS, pero como sé qué es SafeArea en iOS, estoy bastante seguro de que también debería funcionar allí.
manuelwaldner
*** Esto debe establecerse en respuesta aceptada *** Las otras soluciones aquí proporcionan alturas fijas arbitrarias basadas en su propia situación de prueba única
mcmonkeys1
Una respuesta perfecta, pero SafeAreaView no es aplicable para los dispositivos iPhone con una versión inferior a 11
Pradeep
Funcionó muy bien. ¡Gracias!
bruxo00
16

La solución @philipheinser realmente funciona.

Sin embargo, esperaría que el componente StatusBar de React Native se encargue de eso por nosotros.

Desafortunadamente, no es así, pero podemos abstraerlo con bastante facilidad creando nuestro propio componente a su alrededor:

./StatusBar.js

import React from 'react';
import { View, StatusBar, Platform } from 'react-native';

// here, we add the spacing for iOS
// and pass the rest of the props to React Native's StatusBar

export default function (props) {
    const height = (Platform.OS === 'ios') ? 20 : 0;
    const { backgroundColor } = props;

    return (
        <View style={{ height, backgroundColor }}>
            <StatusBar { ...props } />
        </View>
    );
}

./index.js

import React from 'react';
import { View } from 'react-native';

import StatusBar from './StatusBar';

export default function App () {
    return (
      <View>
        <StatusBar backgroundColor="#2EBD6B" barStyle="light-content" />
        { /* rest of our app */ }
      </View>
    )
}
Antes de:

Después:

Asaf Katz
fuente
4

Los react-navigationdocumentos tienen una gran solución para esto. En primer lugar, recomiendan no usar el SafeAreaViewincluido con React Native porque:

Si bien React Native exporta un componente SafeAreaView, tiene algunos problemas inherentes, es decir, si se anima una pantalla que contiene un área segura, provoca un comportamiento de salto. Además, este componente solo es compatible con iOS 10+ y no es compatible con versiones anteriores de iOS o Android. Recomendamos utilizar la biblioteca react-native-safe-area-context para manejar áreas seguras de una manera más confiable.

En cambio, recomiendan react-native-safe-area-context , con el que se vería así:

import React, { Component } from 'react';
import { View, Text, Navigator } from 'react-native';
import { useSafeArea } from 'react-native-safe-area-context';

export default function MyScene({title = 'MyScene'}) {
    const insets = useSafeArea();

    return (
        <View style={{paddingTop: insets.top}}>
            <Text>Hi! My name is {title}.</Text>
        </View> 
    )   
}

Sin embargo, me gustaría señalar que probablemente sea una mejor idea usar el SafeAreaViewque ofrece esta biblioteca, ya que los teléfonos en estos días también pueden tener elementos en la parte inferior que pueden superponerse a los elementos de la interfaz de usuario. Por supuesto, todo depende de tu aplicación. (Para obtener más detalles sobre eso, consulte los react-navigationdocumentos a los que vinculé al principio).

AndyO
fuente
2

Esta es una forma que funciona para iOS :

<View style={{height: 20, backgroundColor: 'white', marginTop: -20, zIndex: 2}}>
   <StatusBar barStyle="dark-content"/></View>
angusyoung84
fuente
1

Puede manejar esto agregando un relleno al componente de la barra de navegación o simplemente agregando una vista que tenga la misma altura que la barra de estado en la parte superior de su árbol de vistas con un color de fondo como lo hace la aplicación de Facebook.

philipheinser
fuente
6
¿Ese valor de altura es fijo y no cambia independientemente del teléfono que tenga? Si es así, ¿dónde puedo encontrar información sobre el valor específico correcto para iOS / Android?
nbkhope
0

Just Simple User React Native Default StatusBar para lograr esta funcionalidad.

<View style={styles.container}>
    <StatusBar backgroundColor={Color.TRANSPARENT} translucent={true} />
    <MapView
      provider={PROVIDER_GOOGLE} // remove if not using Google Maps
      style={styles.map}
      region={{
        latitude: 37.78825,
        longitude: -122.4324,
        latitudeDelta: 0.015,
        longitudeDelta: 0.0121,
      }}
    />
  </View>
Safi Deraiya
fuente