Android Hardware Back Button causes Blank Screen

未关闭
#7,643 2 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
25/100
Issue 类型
缺陷
描述清晰度
需要澄清
活跃度
停滞
技术栈
android, javascript, react-native
领域
mobile-dev

调研方向

从 index.js 中的导航设置和 Android hardwareBackButton 选项开始,然后按照列出的复现步骤,在报告中涉及的 React Native 和 Android 版本上进行操作。将重新启动时的行为与 Native Back Handler 解决方法进行比较;完成标准是使用 hardware Back Button 后重新启动不会显示空白屏幕。

由索引模型根据 Issue 内容生成。

描述

needs triage triage: bug

🐛 Bug Report

Only on Android, when the user uses the Hardware Back Button and they are at the landing screen, the Activity closes. Then when the application is started again I see a blank screen. This happens only if I use the hardware back. If I minimize the application using the hardware home button, then there are no issues.

I read somewhere that I should use the events().registerAppLaunchedListener but that doesn't get invoked.

Have you read the Contributing Guidelines on issues?

Yes, I have read them.

To Reproduce

  1. Create a blank application using the React Native CLI
  2. Install the latest version of the navigation library
  3. Create a Bottom Navigation
  4. As the first tab create a Stack Navigator
  5. Press the hardware back button on the phone
  6. Enter the application again

ERROR: Blank screen.

NOTES: I am using a legacy project that somebody else wrote and I am trying to maintain/update it.

The way the bottom tab bar is created is very weird to me. I found that this code causes the tab bar to appear, however, without this code the tab bar is missing:

// hide the tab bar when navigating to screens that are not in tabBarScreens
Navigation.events().registerCommandListener((name, params) => {
let componentNames = params &&
    params.layout &&
    params.layout.data && [params.layout.data.name]

componentNames =
    componentNames ||
    (params &&
    params.layout &&
    Array.isArray(params.layout) &&
    params.layout
        .map((layout) => layout.data && layout.data.name)
        .filter((c) => c !== undefined))

if (componentNames && componentNames.length === 0) {
    componentNames = undefined
}

componentNames =
    componentNames ||
    (params &&
    params.layout &&
    params.layout.children &&
    params.layout.children
        .map((child) => child.data && child.data.name)
        .filter((c) => c !== undefined))

if (componentNames && componentNames.length === 0) {
    componentNames = undefined
}

componentNames =
    componentNames ||
    (params &&
    params.layout &&
    params.layout.root &&
    params.layout.root.children &&
    params.layout.root.children
        .map((child) => child.data && child.data.name)
        .filter((c) => c !== undefined))
console.log({ name, params })
switch (name) {
    case 'push':
    case 'showModal':
    if (componentNames && componentNames.length > 0) {
        if (
        getTabBarScreen(componentNames[componentNames.length - 1]) ===
        undefined
        ) {
        store.dispatch(setShouldBeVisible(false))
        screenStack.push({
            componentName: componentNames[componentNames.length - 1],
            tabBarVisible: false,
        })
        } else {
        screenStack.push({
            componentName: componentNames[componentNames.length - 1],
        })
        }
    }
    break
    case 'pop':
    case 'dismissModal':
    if (screenStack.length > 1) {
        screenStack.pop()
    }
    break
    case 'popToRoot':
    screenStack = [screenStack[0]]
    break
    case 'setRoot':
    case 'setStackRoot':
    if (componentNames && componentNames.length > 0) {
        screenStack = componentNames.map((c) => {
        return { componentName: c }
        })
    }
    break
}
})

The stack navigation is created as follows:

// This code is executed in the index.js file
let navStack = [
    {
        screenName: MainScreen.screenName(),
        passProps: {
            initial: true,
            navigateToRunning: true,
        },
    },
]
          
const createNavigationStack = (screenList) => {
  return screenList.map((item) => {
    return {
      component: {
        name: item.screenName,
        passProps: item.passProps,
        options: {
          animations: {
            setStackRoot: {
              enabled: false,
            },
          },
          popGesture: false,
          hardwareBackButton: {
            dismissModalOnPress: true,
            popStackOnPress: true,
            bottomTabsOnPress: 'previous',
          },
        },
      },
    }
  })
}
          
Navigation.setRoot(createNavigationStack(navStack))

I have no idea why things are done this way. The only workaround to my problem was to override the Native Back Handler and just disable it:

BackHandler.addEventListener('hardwareBackPress', () => true);

Expected behavior

I expect that the application will return to the last screen that was displayed when it is relaunched.

Actual Behavior

A Blank screen is shown

Your Environment

  • React Native Navigation version: 7.30.2
  • React Native version: 0.70.5
  • Platform(s) (iOS, Android, or both?): Android 11
  • Device info (Simulator/Device? OS version? Debug/Release?): Simulator + Samsung Galaxy S20 FE, both Debug and Release

Reproducible Demo

N/A, the code is proprietry.

Are you willing to resolve this issue by submitting a Pull Request?
  • ✖️   Yes, I have the time, and I know how to start.
  • ✖️   Yes, I have the time, but I don't know how to start. I would need guidance.
  • ✅   No, I don’t have the time and I’m okay to wait for the community / maintainers to resolve this issue.
主要语言
MDX
星标
13.2k
派生
2.6k
平均合并
3 小时 21 分钟
30 天内合并 PR
5

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

wix/react-native-navigation 的其他 Issue

查看 wix/react-native-navigation 的全部 Issue

相似的 Issue

更多 Mobile Dev Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。