Як запобігти накладенню макета на рядок стану iOS


81

Я працюю над підручником для навігації React Native. Я з’ясував, що весь макет починає завантажуватися зверху екрана, а не нижче рядка стану. Це призводить до того, що більшість макетів збігаються з рядком стану. Я можу це виправити, додавши відступ до подання під час їх завантаження. Це справжній спосіб це зробити? Я не думаю, що вручну додавання відступів є реальним способом вирішити це. Чи існує більш елегантний спосіб це виправити?

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

Нижче показані знімки екрана до і після додавання відступів. введіть тут опис зображення


13
Приємне запитання, але, можливо, ви можете обрізати зображення.
Quv

stackoverflow.com/a/39300715/1540350 <- ця відповідь не просто усуне згадану тут проблему, але навіть дасть вам можливість забарвити фон рядка стану в iOS та Android.
Мартін Браун,

Відповіді:


36

Існує дуже простий спосіб це виправити. Зробіть компонент.

Ви можете створити компонент StatusBar і викликати його спочатку після першої обгортки подання у ваших батьківських компонентах.

Ось код того, який я використовую:

'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

Зробивши це та експортувавши у свій основний компонент, назвіть це так:

import StatusBarBackground from './YourPath/StatusBarBackground'

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

 


MidnightBlueнедійсний, розказана Реагувати Native: Попередження: Помилка типу проп: Invalid опора backgroundColorпоставляється
Raptor

2
Це повинно бути midnightblue.
bblincoe

19
Рядок стану iOS не має фіксованого розміру. Він може бути більшим під час спільного використання Wi-Fi або під час дзвінка.
edA-qa mort-ora-y

1
Як я використовую це, коли використовую підключення навігації React із redux, всі сторінки знаходяться або в навігаторі стеку, або в навігаторі вкладок (вкладені) та підключаються до redux
Yasir

5
Якщо ви імпортуєте рідний компонент реакції "StatusBar", а потім скористаєтесь: height: (Platform.OS === 'ios') ? 20 : StatusBar.currentHeight,замість того, ? 20 : 0,щоб отримати той самий результат на Android.
mrroot5

60

Тепер ви можете використовувати те, SafeAreaViewщо входить до складу React Navigation:

<SafeAreaView>
    ... your content ...
</SafeAreaView>

3
Можливо, варто зауважити, що цей компонент зараз входить до складу react-navigationза замовчуванням.
Aᴄʜᴇʀᴏɴғᴀɪʟ

15
це не вирішує проблему перекриття рядка стану - я обгорнув свою програму в SafeAreaView, і моя програма все ще перекриває панель стану. Схоже, це орієнтоване на ситуацію з вирізом iPhone X / закругленими кутами
izikandrw

Ви не обгортаєте в нього свою програму, а обгортаєте екран.
Грег Енніс

О, це приємно! Мені це подобається.
Асаф Кац,

1
@AndreFigueiredo Неправильно. Чудово працює на всіх пристроях iPhone, поки це> iOS 11.
Fellow Stranger

20

Я спробував для цього більш простий спосіб.

Ми можемо отримати висоту рядка стану на android і використовувати SafeAreaView разом з ним, щоб змусити код працювати на обох платформах.

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

Якщо ми вийдемо Platform.OSі StatusBar.currentHeightотримаємо журнали,

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

Висота на: android 24 і висота на: android 24

Тепер ми можемо за бажанням додати поля / відступи до нашого перегляду контейнера за допомогою

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

Остаточний код в App.js знаходиться нижче:

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

1
Я спробував це на android, і воно працює. Я поки що не можу протестувати його на iOS, але оскільки я знаю, що таке SafeArea на iOS, я впевнений, що він також повинен там працювати.
мануельвальднер

1
*** Це слід встановити як прийняту відповідь *** Інші рішення тут надають довільні фіксовані висоти на основі власної ситуації одного тесту
mcmonkeys1

Прекрасна відповідь, але SafeAreaView не застосовується до пристроїв iPhone з версією нижче 11
Прадіп,

Працювали просто чудово. Дякую!
bruxo00,

16

Рішення @philipheinser справді працює.

Однак я би очікував, що компонент StatusBar React Native впорається з цим.

На жаль, цього немає, але ми можемо це легко абстрагувати, створивши навколо нього власний компонент:

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

Після:


4

У react-navigationдокументах мають велике рішення для цього. По-перше, вони рекомендують не використовувати SafeAreaViewвключене з React Native, оскільки:

Хоча React Native експортує компонент SafeAreaView, у нього є деякі невід'ємні проблеми, тобто якщо екран, що містить безпечну зону, анімує, це спричиняє стрибку. Крім того, цей компонент підтримує лише iOS 10+, не підтримуючи старіші версії iOS або Android. Ми рекомендуємо використовувати бібліотеку context-native-safe-area-context для більш надійної обробки безпечних зон.

Натомість вони рекомендують реагувати-рідний-безпечний-область-контекст - з яким це могло б виглядати так:

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

Я хотів би зауважити, що, мабуть, краще використовувати те, SafeAreaViewщо пропонує ця бібліотека, оскільки телефони в наш час можуть також мати елементи внизу, які можуть перекривати елементи інтерфейсу. Звичайно, все залежить від вашого додатка. (Детальніше про це див. У react-navigationдокументах, на які я посилався на початку.)


2

Ось спосіб, який працює для iOS :

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

1

Ви можете впоратися з цим, додавши відступ до компонента панелі навігації або просто опублікуйте представлення, яке має ту саму висоту, що і панель стану у верхній частині дерева перегляду, із фоновим кольором, як це робить програма facebook.


6
Чи встановлено це значення висоти і воно не змінюється незалежно від того, який у вас телефон? Якщо так, де я можу знайти інформацію про правильне конкретне значення для iOS / Android?
nbkhope

0

Для досягнення цієї функціональності просто простий користувач реагує на рідну панель стану за замовчуванням.

<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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.