如何防止布局与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中为状态栏的背景着色。
Martin Braun

Answers:


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是无效的,由React Native告知:警告:道具类型失败:backgroundColor提供的道具无效
Raptor

2
应该是midnightblue
bblincoe

19
iOS状态栏不是固定大小。共享Wifi或通话时可能会更大。
edA-qa mort-ora-y's

1
当将React导航联播与Redux一起使用时,如何使用此功能,所有页面都在堆栈导航器或标签导航器中(嵌套),并与Redux挂钩
Yasir

5
如果您导入react native组件“ StatusBar”,然后使用: height: (Platform.OS === 'ios') ? 20 : StatusBar.currentHeight,而不是? 20 : 0,在Android上获得相同的结果。
mrroot5 '18

60

现在您可以使用SafeAreaViewReact Navigation中包含的内容:

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

2
最好注意,react-navigation默认情况下此组件现在已包括在内。
Aᴄʜᴇʀᴏɴғᴀɪʟ

13
这不能解决状态栏重叠的问题-我将应用程序包装在SafeAreaView中,而我的应用程序仍然与StatusBar重叠。它似乎适合iPhone X的缺口/圆角情况
izikandrw

您不需要在其中包装应用程序,而在其中包装屏幕。
格雷格·恩尼斯

哦,太好了!我喜欢那一个。
Asaf Katz

1
@AndreFigueiredo不正确。适用于所有的iPhone设备罚款,只要它>的iOS 11.
研究员陌生人

17

我尝试了一种更简单的方法。

我们可以在android上获取Status Bar的高度,并与之一起使用SafeAreaView来使代码在两个平台上均能正常工作。

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

如果我们注销Platform.OSStatusBar.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上对其进行测试,但是由于我知道iOS上的SafeArea是什么,我很确定它也可以在iOS上运行。
manuelwaldner '19

***这应该设置为可接受的答案***此处的其他解决方案根据他们自己的单个测试情况提供任意固定的高度
mcmonkeys1

一个完美的答案,但SafeAreaView不适用于版本低于11的iPhone设备
Pradeep

工作得很好。谢谢!
bruxo00

16

@philipheinser解决方案确实有效。

但是,我希望React Native的StatusBar组件将为我们处理它。

不幸的是,它不是,但是我们可以通过围绕它创建自己的组件来轻松地将其抽象化:

./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文档对此有一个很好的解决方案。首先,他们建议 不要使用SafeAreaViewReact Native中包含的内容,因为:

当React Native导出SafeAreaView组件时,它存在一些固有的问题,即,如果包含安全区域的屏幕正在设置动画,它会引起跳跃行为。此外,此组件仅支持iOS 10+,不支持较旧的iOS版本或Android。我们建议使用react-native-safe-area-context库以更可靠的方式处理安全区域。

相反,他们建议使用react-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此库提供的可能是一个更好的主意,因为如今的手机底部可能还具有可以与UI元素重叠的元素。这当然取决于您的应用程序。(有关这方面的更多详细信息,请参阅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

只需Simple User React本机的Default StatusBar即可实现这种功能。

<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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.