Jak zapobiec nakładaniu się układu na pasek stanu iOS

81

Pracuję nad tutorialem do nawigacji w React Native. Dowiedziałem się, że cały układ zaczyna się ładować od góry ekranu, a nie od dołu paska stanu. Powoduje to, że większość układów nakłada się na pasek stanu. Mogę to naprawić, dodając wypełnienie do widoku podczas ich ładowania. Czy to jest właściwy sposób? Nie sądzę, aby ręczne dodawanie dopełnienia było rzeczywistym sposobem rozwiązania tego problemu. Czy jest bardziej elegancki sposób, aby to naprawić?

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

Poniżej przedstawiono zrzuty ekranu przed i po dodaniu wypełnienia. wprowadź opis obrazu tutaj

Klif
źródło
13
Dobre pytanie, ale może mógłbyś przyciąć obrazy.
Quv,
stackoverflow.com/a/39300715/1540350 <- ta odpowiedź nie tylko rozwiąże wspomniany tutaj problem, ale nawet da Ci możliwość pokolorowania tła paska statusu w iOS i Androidzie.
Martin Braun

Odpowiedzi:

36

Jest bardzo prosty sposób, aby to naprawić. Zrób komponent.

Możesz utworzyć komponent StatusBar i wywołać go najpierw po pierwszym opakowaniu widoku w komponentach nadrzędnych.

Oto kod tego, którego używam:

'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

Po wykonaniu tej czynności i wyeksportowaniu go do głównego komponentu, nazwij to w ten sposób:

import StatusBarBackground from './YourPath/StatusBarBackground'

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

 

Luis Rizo
źródło
MidnightBluejest nieważny, opowiedziana przez React Native: Ostrzeżenie: Nie Typ prop: Nieprawidłowy prop backgroundColordostarczone
Raptor
2
Tak powinno być midnightblue.
bblincoe
19
Pasek stanu iOS nie ma stałego rozmiaru. Może być większy podczas udostępniania Wi-Fi lub podczas rozmowy.
edA-qa mort-ora-y
1
Jak mogę to wykorzystać podczas korzystania React nawigację montażowe z Redux, wszystkie strony są albo w stos lub nawigatora karcie nawigatora (zagnieżdżone) i hakiem z Redux
Jaser
5
Jeśli zaimportujesz reagujący komponent natywny „StatusBar”, a następnie użyjesz: height: (Platform.OS === 'ios') ? 20 : StatusBar.currentHeight,zamiast tego ? 20 : 0,uzyskasz ten sam wynik na Androidzie.
mrroot5
60

Teraz możesz użyć tego, SafeAreaViewco jest zawarte w React Navigation:

<SafeAreaView>
    ... your content ...
</SafeAreaView>
Greg Ennis
źródło
3
Warto zauważyć, że ten komponent jest react-navigationteraz domyślnie zawarty w programie .
Aᴄʜᴇʀᴏɴғᴀɪʟ
15
nie rozwiązuje to problemu nakładania się paska stanu - zawinąłem aplikację w SafeAreaView, a moja aplikacja nadal zachodzi na pasek stanu. Wydaje się, że jest nastawiony na wycięcie / zaokrąglone rogi iPhone'a X
izikandrw
Nie zawijasz w nią swojej aplikacji, zawijasz w nią ekran.
Greg Ennis
Och, to miło! Lubie ten.
Asaf Katz
1
@AndreFigueiredo Nieprawidłowe. Działa dobrze na wszystkich urządzeniach iPhone, o ile jest> iOS 11.
Fellow Stranger
20

Wypróbowałem prostszy sposób.

Możemy uzyskać wysokość paska stanu na Androidzie i użyć razem z nim SafeAreaView, aby kod działał na obu platformach.

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

Jeśli się wylogujemy Platform.OSi StatusBar.currentHeightotrzymamy logi,

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

Wysokość na: Android 24 i Wysokość na: Android 24

Możemy teraz opcjonalnie dodać margines / dopełnienie do naszego widoku kontenera za pomocą

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

Ostateczny kod w App.js znajduje się poniżej:

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
źródło
1
Wypróbowałem to na Androidzie i działa. Nie mogę jeszcze przetestować tego na iOS, ale ponieważ wiem, co SafeArea jest na iOS, jestem prawie pewien, że powinno też tam działać.
manuelwaldner
1
*** To powinno być ustawione na akceptowaną odpowiedź *** Inne rozwiązania zapewniają arbitralne ustalone wysokości w oparciu o ich własną pojedynczą sytuację testową
mcmonkeys1
Doskonała odpowiedź, ale SafeAreaView nie dotyczy urządzeń iPhone z wersją poniżej 11
Pradeep
Działało dobrze. Dzięki!
bruxo00
16

Rozwiązanie @philipheinser rzeczywiście działa.

Spodziewałbym się jednak, że komponent StatusBar React Native zajmie się tym za nas.

Niestety tak nie jest, ale możemy to dość łatwo wyodrębnić, tworząc wokół niego własny komponent:

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

Po:

Asaf Katz
źródło
4

Dokumenty react-navigationmają na to świetne rozwiązanie. Po pierwsze, zaleca się nie używać SafeAreaViewdołączonej React Native ponieważ:

Chociaż React Native eksportuje składnik SafeAreaView, ma pewne nieodłączne problemy, np. Animacja ekranu zawierającego bezpieczny obszar powoduje skakanie. Ponadto ten komponent obsługuje tylko iOS 10+, bez wsparcia dla starszych wersji iOS lub Androida. Zalecamy korzystanie z biblioteki kontekstowej react-native-safe-area, aby obsługiwać bezpieczne obszary w bardziej niezawodny sposób.

Zamiast tego zalecają reakcję-natywny-bezpieczny-kontekst-obszaru - z którym wyglądałoby to tak:

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

Chciałbym zauważyć, że prawdopodobnie lepszym pomysłem jest skorzystanie z SafeAreaViewtego, co oferuje ta biblioteka, ponieważ telefony w dzisiejszych czasach mogą mieć również elementy na dole, które mogą nakładać się na elementy interfejsu użytkownika. Wszystko zależy oczywiście od Twojej aplikacji. (Więcej informacji na ten temat można znaleźć w react-navigationdokumentach, do których utworzyłem łącze na początku).

AndyO
źródło
2

Oto sposób, który działa na iOS :

<View style={{height: 20, backgroundColor: 'white', marginTop: -20, zIndex: 2}}>
   <StatusBar barStyle="dark-content"/></View>
angusyoung84
źródło
1

Możesz sobie z tym poradzić, dodając wypełnienie do komponentu paska nawigacyjnego lub po prostu reklamując widok, który ma taką samą wysokość jak pasek stanu u góry drzewa widoku, z kolorem tła, tak jak robi to aplikacja na Facebooku.

philipheinser
źródło
6
Czy ta wartość wysokości jest stała i nie zmienia się niezależnie od posiadanego telefonu? Jeśli tak, gdzie mogę znaleźć informacje o prawidłowej konkretnej wartości dla systemu iOS / Android?
nbkhope
0

Just Simple User React natywny Default StatusBar, aby osiągnąć tę funkcjonalność.

<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
źródło