So verhindern Sie, dass sich das Layout mit der iOS-Statusleiste überschneidet

81

Ich arbeite an einem Tutorial für React Native Navigation. Ich fand heraus, dass das gesamte Layout vom oberen Bildschirmrand anstatt unterhalb der Statusleiste geladen wird. Dies führt dazu, dass sich die meisten Layouts mit der Statusleiste überschneiden. Ich kann dies beheben, indem ich der Ansicht beim Laden einen Abstand hinzufüge. Ist das der eigentliche Weg, es zu tun? Ich denke nicht, dass das manuelle Hinzufügen von Polstern ein tatsächlicher Weg ist, dies zu lösen. Gibt es eine elegantere Möglichkeit, dies zu beheben?

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

Unten sehen Sie die Screenshots vor und nach dem Hinzufügen der Polsterung. Geben Sie hier die Bildbeschreibung ein

Cliff
quelle
13
Schöne Frage, aber vielleicht könnten Sie die Bilder verkleinern.
Quv
stackoverflow.com/a/39300715/1540350 <- Diese Antwort behebt nicht nur das hier erwähnte Problem, sondern bietet Ihnen auch die Möglichkeit, den Hintergrund der Statusleiste in iOS und Android einzufärben.
Martin Braun

Antworten:

36

Es gibt eine sehr einfache Möglichkeit, dies zu beheben. Machen Sie eine Komponente.

Sie können eine StatusBar-Komponente erstellen und diese nach dem ersten View-Wrapper in Ihren übergeordneten Komponenten zuerst aufrufen.

Hier ist der Code für den, den ich benutze:

'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

Nachdem Sie dies getan und in Ihre Hauptkomponente exportiert haben, rufen Sie es folgendermaßen auf:

import StatusBarBackground from './YourPath/StatusBarBackground'

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

 

Luis Rizo
quelle
MidnightBlueist ungültig, von React Native mitgeteilt: Warnung: Fehlgeschlagener Requisitentyp: Ungültige Requisite backgroundColorgeliefert
Raptor
2
Es sollte sein midnightblue.
Bblincoe
19
Die iOS-Statusleiste hat keine feste Größe. Es kann größer sein, wenn Sie Wifi oder einen Anruf teilen.
edA-qa mort-ora-y
1
Wie verwende ich dies, wenn ich React Navigation Hookup mit Redux verwende? Alle Seiten befinden sich entweder in einem Stack Navigator oder Tab Tab Navigator (verschachtelt) und Hook mit Redux
Yasir
5
Wenn Sie die native Reaktionskomponente "StatusBar" importieren und dann verwenden: height: (Platform.OS === 'ios') ? 20 : StatusBar.currentHeight,Stattdessen erhalten ? 20 : 0,Sie auf Android das gleiche Ergebnis.
mrroot5
60

Jetzt können Sie Folgendes verwenden, SafeAreaViewdas in React Navigation enthalten ist:

<SafeAreaView>
    ... your content ...
</SafeAreaView>
Greg Ennis
quelle
2
Es ist gut zu beachten, dass diese Komponente react-navigationjetzt standardmäßig enthalten ist.
Aᴄʜᴇʀᴏɴғᴀɪʟ
14
Dies löst das Problem der Überlappung der Statusleiste nicht. Ich habe meine App in SafeAreaView verpackt und meine App überlappt immer noch die Statusleiste. Es scheint auf die iPhone X Kerbe / abgerundete Ecken Situation ausgerichtet zu sein
izikandrw
Sie wickeln Ihre App nicht ein, sondern einen Bildschirm.
Greg Ennis
Ohh, das ist schön! Ich mag das.
Asaf Katz
1
@AndreFigueiredo Nicht korrekt. Funktioniert gut auf allen iPhone-Geräten, solange es> iOS 11 ist.
Fellow Stranger
19

Ich habe es auf einfachere Weise versucht.

Wir können die Höhe der Statusleiste auf Android ermitteln und SafeAreaView zusammen mit dieser verwenden, damit der Code auf beiden Plattformen funktioniert.

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

Wenn wir uns abmelden Platform.OSund StatusBar.currentHeightdie Protokolle erhalten,

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

Höhe ein: Android 24 und Höhe ein: Android 24

Wir können jetzt optional Rand / Abstand zu unserer Containeransicht hinzufügen, indem wir

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

Der endgültige Code in App.js ist unten:

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
quelle
1
Ich habe es auf Android versucht und es funktioniert. Ich kann es noch nicht unter iOS testen, aber da ich weiß, was SafeArea unter iOS ist, bin ich mir ziemlich sicher, dass es auch dort funktionieren sollte.
Manuelwaldner
1
*** Dies sollte auf akzeptierte Antwort gesetzt werden *** Die anderen Lösungen hier bieten willkürliche feste Höhen basierend auf ihrer eigenen einzelnen Testsituation
mcmonkeys1
Eine perfekte Antwort, aber SafeAreaView gilt nicht für iPhone-Geräte mit einer Version unter 11
Pradeep
Hat gut funktioniert. Vielen Dank!
bruxo00
16

@philipheinser Lösung funktioniert in der Tat.

Ich würde jedoch erwarten, dass die StatusBar- Komponente von React Native dies für uns erledigt .

Leider nicht, aber wir können das ganz einfach abstrahieren, indem wir unsere eigene Komponente darum herum erstellen:

./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>
    )
}
Vor:

Nach:

Asaf Katz
quelle
4

Die react-navigationDokumente haben eine großartige Lösung dafür. Zunächst einmal empfehlen sie , das SafeAreaViewin React Native enthaltene nicht zu verwenden, weil:

Während React Native eine SafeAreaView-Komponente exportiert, treten einige inhärente Probleme auf. Wenn ein Bildschirm mit einem sicheren Bereich animiert wird, führt dies zu nervösem Verhalten. Darüber hinaus unterstützt diese Komponente nur iOS 10+ ohne Unterstützung für ältere iOS-Versionen oder Android. Wir empfehlen, die Kontextbibliothek "React-Native-Safe-Area-Context" zu verwenden, um sichere Bereiche zuverlässiger zu behandeln.

Stattdessen empfehlen sie den Kontext "React-Native-Safe-Area" - mit dem es so aussehen würde:

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

Ich möchte darauf hinweisen, dass es wahrscheinlich eine bessere Idee ist, das zu verwenden SafeAreaView, was diese Bibliothek bietet, da Telefone heutzutage möglicherweise auch Elemente am unteren Rand haben, die UI-Elemente überlappen können. Es hängt natürlich alles von Ihrer App ab. (Weitere Informationen hierzu finden Sie in den react-navigationDokumenten, auf die ich am Anfang verlinkt habe.)

AndyO
quelle
2

Hier ist ein Weg, der für iOS funktioniert :

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

Sie können dies tun, indem Sie Ihrer Navigationsleistenkomponente eine Auffüllung hinzufügen oder einfach eine Ansicht hinzufügen, die dieselbe Höhe wie die Statusleiste oben in Ihrem Ansichtsbaum hat und eine Hintergrundfarbe wie die Facebook-App aufweist.

philipheinser
quelle
6
Ist dieser Höhenwert festgelegt und ändert sich nicht, egal welches Telefon Sie haben? Wenn ja, wo finde ich Informationen zum richtigen spezifischen Wert für iOS / Android?
nbkhope
0

Nur einfacher Benutzer Reagieren Sie auf die native Standardstatusleiste, um diese Funktionalität zu erreichen.

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