【问题标题】:How to prevent layout from overlapping with iOS status bar如何防止布局与iOS状态栏重叠
【发布时间】:2017-07-24 19:14:03
【问题描述】:

我正在为 React Native 导航使用 tutorial。我发现所有布局都是从屏幕顶部而不是状态栏下方开始加载的。这会导致大多数布局与状态栏重叠。我可以通过在加载视图时向视图添加填充来解决此问题。这是实际的方法吗?我不认为手动添加填充是解决它的实际方法。有没有更优雅的方法来解决这个问题?

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

下面显示了添加填充之前和之后的屏幕截图。

【问题讨论】:

标签: ios react-native


【解决方案1】:

现在您可以使用 React Navigation 中包含的 SafeAreaView

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

【讨论】:

  • 请注意,这个组件现在默认包含在react-navigation 中。
  • 这并不能解决状态栏重叠的问题——我将我的应用程序包装在 SafeAreaView 中,我的应用程序仍然与状态栏重叠。它似乎是针对 iPhone X 缺口/圆角情况的
  • 你不是把你的应用包裹在里面,而是在里面包裹一个屏幕。
  • 哦,太好了!我喜欢那个。
  • @AndreFigueiredo 不正确。适用于所有 iPhone 设备,只要它 > iOS 11。
【解决方案2】:

有一个非常简单的方法可以解决这个问题。制作一个组件。

您可以创建一个 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 提供
  • 应该是midnightblue
  • iOS 状态栏不是固定大小。共享 Wifi 或通话时可以更大。
  • 在使用 React 导航连接和 redux 时如何使用它,所有页面都在堆栈导航器或选项卡导航器(嵌套)中并与 redux 挂钩
  • 如果你导入 react 原生组件 "StatusBar" 然后使用:height: (Platform.OS === 'ios') ? 20 : StatusBar.currentHeight, 而不是 ? 20 : 0, 在 Android 上你会得到相同的结果。
【解决方案3】:

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

我们可以在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
  }
});

【讨论】:

  • 我在 android 上试过了,它工作正常。我还不能在 iOS 上测试它,但我知道 iOS 上的 SafeArea 是什么,我很确定它也应该在那里工作。
  • ***这应该设置为接受的答案***这里的其他解决方案根据他们自己的单一测试情况提供任意固定高度
  • 一个完美的答案,但 SafeAreaView 不适用于版本低于 11 的 iPhone 设备
  • 工作得很好。谢谢!
  • 最好的。工作。我们为什么要在这里检查 ios?
【解决方案4】:

@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>
    )
}
前:

后:

【讨论】:

    【解决方案5】:

    react-navigation 文档对此有很好的解决方案。首先,they recommend使用 React Native 中包含的 SafeAreaView,因为:

    当 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 文档。)

    【讨论】:

    • 已弃用
    • @AcauãPitta 提出索赔时请提供来源
    • useSafeArea 根据文档已弃用:github.com/th3rdwave/react-native-safe-area-context#usesafearea。他们建议使用 useSafeAreaInsets 钩子。
    • 在需要更大灵活性的情况下使用此钩子,但如果您不这样做,请使用 SafeAreaView 和 SafeAreaProvider,因为它是最干净的解决方案
    【解决方案6】:

    这是一种适用于iOS的方法:

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

    【讨论】:

      【解决方案7】:

      您可以通过向导航栏组件添加填充来处理此问题,或者只是在视图树顶部使用背景颜色广告一个与状态栏具有相同高度的视图,就像 facebook 应用程序那样。

      【讨论】:

      • 这个高度值是固定的,不管你有什么手机都不会改变?如果是这样,我在哪里可以找到有关 iOS / Android 的正确特定值的信息?
      【解决方案8】:

      只需简单的用户反应原生默认状态栏即可实现此功能。

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

      【讨论】:

        【解决方案9】:

        如果你把 SaveAreaView 和 StatusBar 结合起来,你就明白了。

        https://reactnative.dev/docs/statusbar https://reactnative.dev/docs/safeareaview

        这样做:

        <SafeAreaView>
          <View style={{flex: 1}}>
            <StatusBar translucent={false} backgroundColor="#fff" />
        
            // Your dark magic here
          </View>
        </SafeAreaView>
        

        【讨论】:

          猜你喜欢
          • 2021-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-10
          • 1970-01-01
          • 2013-09-29
          • 1970-01-01
          相关资源
          最近更新 更多