facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.79k stars 24.29k forks source link

keyboardDidHide doesn't get fired on some devices #33056

Closed pistonsky closed 1 year ago

pistonsky commented 2 years ago

Description

I see this magic number in native code for Keyboard on android:

mMinKeyboardHeightDetected = (int) PixelUtil.toPixelFromDIP(60);

In my app, when I setup a listener for keyboardDidHide event, the handler doesn't get fired. Instead, keyboardDidShow handler gets fired with endCoordinates.height value of around 73. I propose to up that magic number to 80 value or to add top notch value on top of 60, since this commit changed the logic for keyboardDidHide event.

I was able to fix the bug by adding these lines on top of my keyboardDidShow handler:

  _keyboardDidShow = (e) => {
    if (e.endCoordinates.height < 100) {
      this._keyboardDidHide();
      return;
    }
    /* other code */
  }

The device I used was Samsung Galaxy S20FE. It has a big notch at the top and it also has irregular bigger than usual height of bottom buttons (the bug is only there when using 3-button navigation. When using gesture navigation the bug does not occur).

Version

0.67.1

Output of npx react-native info

System: OS: macOS 12.2 CPU: (8) x64 Apple M1 Memory: 29.16 MB / 16.00 GB Shell: 5.8 - /bin/zsh Binaries: Node: 16.2.0 - ~/.nvm/versions/node/v16.2.0/bin/node Yarn: 1.22.17 - ~/dev/emma-master/node_modules/.bin/yarn npm: 7.13.0 - ~/.nvm/versions/node/v16.2.0/bin/npm Watchman: 2022.01.17.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.2 - /Users/pistonsky/.rvm/rubies/ruby-2.7.4/bin/pod SDKs: iOS SDK: Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3 Android SDK: API Levels: 23, 28, 29, 30, 31 Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.2, 30.0.3 System Images: android-29 | Google APIs ARM 64 v8a, android-30 | Google APIs ARM 64 v8a, android-30 | Google APIs Intel x86 Atom, android-31 | Google APIs ARM 64 v8a, android-31 | Google Play ARM 64 v8a, android-32 | Google Play ARM 64 v8a, android-32 | Google Play Intel x86 Atom_64, android-S | Google APIs ARM 64 v8a, android-Sv2 | Google APIs ARM 64 v8a Android NDK: 22.1.7171670 IDEs: Android Studio: 2020.3 AI-203.7717.56.2031.7621141 Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild Languages: Java: 1.8.0_275 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 17.0.2 => 17.0.2 react-native: 0.67.1 => 0.67.1 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

Unfortunately, I was not able to reproduce this bug on 0.67.1 clean install, even using the same device that had that bug on my project. But still, that 60 magic value in combination with those changes 4 months ago seems to be the cause of it.

Snack, code example, screenshot, or link to a repository

No response

fabOnReact commented 2 years ago

Unfortunately, I was not able to reproduce this bug on 0.67.1 clean install, even using the same device that had that bug on my project. But still, that 60 magic value in combination with those changes 4 months ago seems to be the cause of it. any advice on how to reproduce the problem?

You are experiencing the issue with this device?

I propose to up that magic number to 80 value or to add top notch value on top of 60, since this commit changed the logic for keyboardDidHide event.

https://github.com/facebook/react-native/commit/8bef3b1f1136ab5c2f2309a3101a7d9626ced1f5#diff-c6c68fb9580db5698d241fdd97b31a25ca1fdc061023a1bf1959f64fc4a00743R780

You mean apply similar logic mMinKeyboardHeightDetected = (int) PixelUtil.toPixelFromDIP(60); also with notch? Could this cause issues to other devices and use cases?

It has a big notch at the top and it also has irregular bigger than usual height of bottom buttons (the bug is only there when using 3-button navigation.

It has a big notch at the top. => I don't see a notch on the device you are using from the picture.

The bug is only there when using 3-button navigation.

Could you give me an insight on the reason you can not reproduce this with a clean install?

Thanks a lot for the report. I'll have a look into it :pray:.

fabOnReact commented 2 years ago

Your issue is in this lines of code. You say that keyboardDidShow is triggered when it should not, caused by a certain combination of keyboardHeight and notchHeight. If I correctly understand you experience this when you navigate backwards with this button.

https://github.com/facebook/react-native/blob/cfa42605989eee5a9de42bdb1259fb7f4d9451fb/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java#L667-L679

lyswhut commented 2 years ago

The same problem occurs on Xiaomi devices, if virtual navigation keys are enabled, the keyboardDidShow event is still sent even if the keyboard does not pop up. But after only needing to rotate the screen orientation once, this event will resume to working normally

lyswhut commented 2 years ago

I recorded a video demonstrating it:

https://user-images.githubusercontent.com/20365169/158751241-0391a29e-bac7-4987-bdaa-6bbcfc53f52f.mp4

The code for the application to listen for keyboard events is as follows:

Keyboard.addListener('keyboardDidShow', (e) => {
  Alert.alert('keyboardDid --> Show', 'keyboard height: ' + e.endCoordinates.height, [
    {
      text: 'Cancel',
    },
  ])
})
Keyboard.addListener('keyboardDidHide', (e) => {
  Alert.alert('keyboardDid --> Hide', 'keyboard height: ' + e.endCoordinates.height, [
    {
      text: 'Cancel',
    },
  ])
})

The keyboardDidShow event is triggered immediately after the application starts (actually the keyboard doesn't show), and the keyboard height is 70.333 ... After rotating the screen, keyboard events resume work

pistonsky commented 2 years ago

@lyswhut Can you provide the source code of the complete app that you used to record the demo please?

pistonsky commented 2 years ago

I found the cause of this issue in my project. The reason was usage of react-native-extra-dimensions-android package.

When you have a style in your project like so:

const styles = StyleSheet.create({
  container: {
    height: ExtraDimensions.get('REAL_WINDOW_HEIGHT'),
  },
});

all keyboard events will be broken. When app starts, you will receive keyboardDidShow event right away, with some random relatively small value (for example, Samsung S20 has 81.52381134033203 value). However, no keyboard is shown, so this event should not even be dispatched. This can potentially break bottom tab bar if you set it to auto-hide on keyboard. Be aware!

Also, when you actually do focus some text input, the height of keyboard within the event will be wrong - it will be more than it actually is, by the value that comes when you hide the keyboard. And when you hide the keyboard, no keyboardDidHide event will be dispatched. Instead, you will receive keyboardDidShow.

This behavior occurs on some devices, not all of them. For example, I've seen it on Samsung S20 when navigation is setup to use 3-button navigation (soft navigation bar at the bottom).

How to reproduce

Start a new react native project, then install this package, and add code above. I've setup a repo for convenience

lyswhut commented 2 years ago

I found the cause of this issue in my project. The reason was usage of react-native-extra-dimensions-android package.

I also use this package, as long as any method of this package is called, this problem occurs, for example:

// index.js
import ExtraDimensions from 'react-native-extra-dimensions-android'
import { Keyboard, Alert } from 'react-native'

ExtraDimensions.getRealWindowWidth()

Keyboard.addListener('keyboardDidShow', (e) => {
  Alert.alert('keyboardDid --> Show', 'keyboard height: ' + e.endCoordinates.height, [
    {
      text: 'Cancel',
    },
  ])
})
Keyboard.addListener('keyboardDidHide', (e) => {
  Alert.alert('keyboardDid --> Hide', 'keyboard height: ' + e.endCoordinates.height, [
    {
      text: 'Cancel',
    },
  ])
})
github-actions[bot] commented 2 years ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] commented 1 year ago

This issue was closed because it has been stalled for 7 days with no activity.