最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】react-navigation导航栏被状态栏遮盖挡住了一部分

React Native crifan 6648浏览 0评论

通过:

【已解决】ReactNative的导航库:native-navigation vs react-native-navigation

确认了使用:

native-navigation

而通过官网:

https://reactnavigation.org

的demo:

https://expo.io/@react-navigation/NavigationPlayground

已经发现了:

android手机中,导航栏的部分,顶部被状态栏遮挡了:

以为是特殊情况呢

结果自己去:

【已解决】ReactNative中实现底部Tab页面和顶部导航栏

折腾的效果,问题依旧

所以确认是库的问题了,所以要去解决

react-navigation navigation bar status bar

react-navigation navigation bar status bar overlap

Status bar overlaps with app/nav bar · Issue #71 · expo/expo

[Question] Avoid status bar overlap on all screens · Issue #2410 · react-community/react-navigation

Play nicely with translucent StatusBar on Android · Issue #12 · react-community/react-navigation

去试试iPhone中是否有此问题。

iPhone中没有此问题

基本上确认了:

不是expo的问题

而是android需要特殊处理。

[Android] StatusBar Translucent not working in Android 4.x.x after upgrading to react 0.23 · Issue #6876 · facebook/react-native

参考:

Configuring StatusBar | Expo v19.0.0 documentation

后来看到更新版本的文档:

Configuring StatusBar | Expo latest documentation

里面除了解释,还有参考代码和写法。

去试了试:

app.json

{
  "expo": {
    "sdkVersion": "21.0.0",
    "androidStatusBar": {
      "backgroundColor": "#C2185B"
    }
  }
}

但是没有效果。

androidStatusBar expo

statusbar covering the tabs in expo app on android · Issue #1168 · react-community/react-navigation

StatusBar doesn’t work on android · Issue #90 · expo/expo

去试试:

App.js

const RseApp = StackNavigator(
  {
    Home: { screen: Home },
    Profile: { screen: Profile },
  },
  {
    navigationOptions: {
      headerStyle: {
        marginTop: Expo.Constants.statusBarHeight
      }
    }
  }
);

结果:

android中就正常了:

ios还是保持正常的,不受影响。

【总结】

expo的做法:

Configuring StatusBar | Expo v19.0.0 documentation

对于android默认是用了透明的状态栏,导致andorid中,有些navigation libraries不支持这个。

所以解决办法是:

方法1:设置backgroundColor:此处设置了,但是没用。

方法2:在入口的app:

App.js

添加Expo.Constants.statusBarHeight,代码:

const RseApp = StackNavigator(
  {
    Home: { screen: Home },
    Profile: { screen: Profile },
  },
  {
    navigationOptions: {
      headerStyle: {
        marginTop: Expo.Constants.statusBarHeight
      }
    }
  }
);

即可。

【后记】

参考:

Set STATUSBAR_HEIGHT for android. by gunn · Pull Request #2446 · react-community/react-navigation

其实是react-navigation自己的bug,此处是直接修改了代码:

import { Animated, Platform, StyleSheet, View, StatusBar } from ‘react-native’;
// const STATUSBAR_HEIGHT = Platform.OS === ‘ios’ ? 20 : 0;
const STATUSBAR_HEIGHT = Platform.OS === ‘ios’ ? 20 : StatusBar.currentHeight;

同时把之前的App.js的代码注释掉:

const RseApp = StackNavigator(
  {
    Home: { screen: Home },
    Profile: { screen: Profile },
  },
  // Note: Not need add following code if update react-navigation code according to:
  // Set STATUSBAR_HEIGHT for android. by gunn · Pull Request #2446 · react-community/react-navigation
  // and for new version react-navigation, maybe has fixed this bug
  // {
  //   navigationOptions: {
  //     headerStyle: {
  //       marginTop: Expo.Constants.statusBarHeight
  //     }
  //   }
  // }
);

所以:

暂时就是自己改

node_modules/react-navigation/src/views/Header/Header.js

代码,就可以了。

之后:希望新版的react-navigation已经修复此问题。

不过改fix,有人不同意,也评论了,但是对于此处api <19或<21的android来说,暂时我觉得可以忽略。所以不是大问题。

不过,如果到时候如果导致native的app的顶部多出了额外的空白,则再考虑如何消除和避免此问题,或者干脆忽略掉expo的问题。

而要完美的解决该问题,则可以参考:

Play nicely with translucent StatusBar on Android · Issue #12 · react-community/react-navigation

dantman的解释:

Getting the correct status bar underlap height is actually pretty complex.

  • iOS’ StatusBar height is normally hardcoded at 20 which is correct for all currently released iOS devices. It can grow during calls due to the call indicator, however iOS actually pushes the viewport down clipping the bottom of the viewport instead of growing the status bar’s height, so the relevant height stays at 20.

  • However Apple is releasing a new iPhone X which has a StatusBar height of 44. And they’re doing this alongside a release of an iPhone 8 that has as StatusBar height of 20. So iOS’ StatusBar height is now hardware dependent.

  • Android has different StatusBar heights, it was 25 up till Marshmallow (API level 23) when it changed to 24. Some devices like the Kindle Fire change the value. And it’s also dynamic, on tablets it can be 32px. Though as long as there is no circumstance where the "status_bar_height", "dimen", "android" trick doesn’t return a value StatusBar.currentHeight takes care of this for Android.

  • However while that’s all fine for getting the height of the StatusBar, than doesn’t actually tell you if the StatusBar is overlapping (is set to translucent), if it’s not translucent than the overlapping height is 0.

  • If the user is running vanilla react-native on Android with no StatusBar tweaks, the StatusBar is not translucent and the overlapping height is 0.

  • But even if the user sets the StatusBar to translucent, that doesn’t mean that it is actually translucent. react-native supports android all the way back to API level 16. Whether the StatusBar is translucent if you set it depends on the version of Android and how you set it to translucent.

    • Android introduced the ability to set the StatusBar to translucent statically using android:windowTranslucentStatus in KitKat (API level 19), this is how Expo does it.

    • But it wasn’t till Lollipop (API level 21) that it became possible to set it translucent dynamically, the way <StatusBar translucent /> does it.

I think the long term solution is going to be to make react-native support StatusBar.currentHeight on all platforms and add an StatusBar.isTranslucent() + event emitter api.

By the way, just to make everyone’s lives worse 😉. For awhile now Android’s soft keys (the back/home/recents buttons at the bottom of the screen which are software based on some devices) have had the ability to set them as translucent as well; which is fine since that’s only a problem if the app author does it (at which point they may complain about bottom aligned tabs). Except, the new iPhone X now has a soft home indicator instead of the home button which underlaps just like the StatusBar, and that underlapping footer is mandatory. And just to rub salt in that, in landscape mode you also need to inset from the edges of the screen, except this horizontal inset should be done in your content instead of the views that contain them (so things like dividers still span to the edges).

So a <NavigationFooter /> api for soft keys and the soft home indicator that works like the proposed StatusBar API will probably be a good idea as well. And then something else to deal with the horizontal insets. Maybe something higher level as well like <StatusBar.Spacer /> to make this easy to deal with.

转载请注明:在路上 » 【已解决】react-navigation导航栏被状态栏遮盖挡住了一部分

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.171 seconds, using 22.05MB memory