Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on Interactive Keyboard [Android only] #203

Closed
ImBeCiliC opened this issue Aug 11, 2023 · 10 comments
Closed

Crash on Interactive Keyboard [Android only] #203

ImBeCiliC opened this issue Aug 11, 2023 · 10 comments
Assignees
Labels
🤖 android Android specific 🎯 crash Library triggers a crash of the app 👆 interactive keyboard Anything related to interactive keyboard dismissing

Comments

@ImBeCiliC
Copy link

Describe the bug
Hard crash with this error been thrown

Reproduction is possible in your example repo.

Upon routing into a deeper stack. Home -> Chat with Keyboard Handler -> Forward Friend --- Back Button ---> Chat with Keyboard Handler -> Open Keyboard -> Full Android Crash

java.lang.IllegalArgumentException: Can not copy bounds as view is not laid out or attached to window
08-11 12:59:11.486  4446  4446 E AndroidRuntime: 	at com.reactnativekeyboardcontroller.extensions.ViewKt.copyBoundsInWindow(View.kt:45)

Repo for reproducing
https://github.com/ImBeCiliC/keyboard-controller-crash-1

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'interactive keyboard'
  2. Open Keyboard
  3. Press Yellow Navigation Button
  4. Navigate Back
  5. Open Keyboard
  6. Try to Scroll the Chat View
  7. CRASH

Smartphone (please complete the following information):

  • OS: Android only
  • RN version: as in example repo
  • RN architecture: as in example repo
  • JS engine: as in example repo
  • Library version: 1.5.8

Additional context
In the Example the height of the fake view is strange after back navigation

Removing the KeyboardGestureArea removes the crash. Also in my example repo so you can check it out.

Appreciate the nice library and helped improve the React Native Keyboard issues we had in the past 🎉

@kirillzyusko
Copy link
Owner

Thanks @ImBeCiliC for reporting the problem! I'll have a look and will try to reproduce/fix the problem!

@kirillzyusko kirillzyusko added 🤖 android Android specific 👆 interactive keyboard Anything related to interactive keyboard dismissing 🎯 crash Library triggers a crash of the app labels Aug 11, 2023
@kirillzyusko
Copy link
Owner

Okey-dokey, I figured it out.

The problems occurs because isLaidOut=false. It happens because of "height of the fake view is strange after back navigation" (view is not fully visible and thus it's not laid out).

"height of the fake view is strange after back navigation"

I think you are referring to this anomaly:

It happens because of the fact, that hooks by default changes inputMode to adjustResize on mount and to default on unmount. Since you are entering new screen - it'll change input mode to adjustResize. When you go back - it'll unmount component and will restore default mode (default mode is adjustPan in example app). So when you opened interactive keyboard by navigation back your inputMode will be adjustResize and it'll produce such "anomaly" (actually it's not an anomaly - that's how android works).

Try to replace KeyboardAnimation content with following code and reproduce your issue. I've tried and it has gone for me:

import React, { useContext } from 'react';
import { Animated, TextInput, View } from 'react-native';
import {
  KeyboardContext,
  useKeyboardAnimation,
  useKeyboardAnimationReplica,
} from 'react-native-keyboard-controller';
import styles from './styles';

const useKeyboardAnimationInNativeStack = () => {
  const context = useContext(KeyboardContext);

  return context.animated;
};

export default function KeyboardAnimation() {
  const { height, progress } = useKeyboardAnimationInNativeStack();

  return (
    <View style={styles.container}>
      <View>
        <Animated.View
          style={{
            width: 50,
            height: 50,
            backgroundColor: 'green',
            borderRadius: 25,
            transform: [
              {
                translateX: progress.interpolate({
                  inputRange: [0, 1],
                  outputRange: [0, 100],
                }),
              },
            ],
          }}
        />
      </View>
      <View>
        <TextInput
          style={{
            width: 200,
            marginTop: 50,
            height: 50,
            backgroundColor: 'yellow',
          }}
        />
        <View style={[styles.row, styles.center]}>
          <Animated.View
            style={{
              width: 50,
              height: 50,
              backgroundColor: 'red',
              borderRadius: 25,
              transform: [{ translateY: height }],
            }}
          />
        </View>
      </View>
    </View>
  );
}

Basically I highly recommend you to create your own versions of useKeyboardAnimation and other hooks - the default behavior (change soft input mode on mount/unmount) is suitable for a lot of use cases, however in a lot of use cases you may need to control inputMode granularly (for example use it in specific stack).

The common use case also would be to change input mode on focus event of react-navigation (it's better, than mount/unmount lifecycles).

And another common use case is to enable adjustResize globally for all application and change to other inputModes only when it's needed. In this case you also can create your own versions of hooks from this library:

const useKeyboardAnimationInNativeStack = () => {
  const context = useContext(KeyboardContext);

  return context.animated;
};

Let me know if something is unclear. Do you think I should add a page to the documentation explaining this concept in details?

@ImBeCiliC
Copy link
Author

@kirillzyusko thanks for the detailed clarification. It is now working for me 🎉

Could be really helpful to others to have this section in the documentation.
If you don't need any code changes feel free to close the issue.

@kirillzyusko
Copy link
Owner

@ImBeCiliC actually I already wrote about this https://kirillzyusko.github.io/react-native-keyboard-controller/docs/guides/building-own-hook

Maybe it can be somehow improved? What do you think I should add to be sure that people are aware about this?

@4yki
Copy link

4yki commented Sep 26, 2023

Hi @kirillzyusko ! First of all - huge thx for this lib.
I have this sort of crash right now ... and I'm sure that the problem is not because of changing windowSoftInputMode as I have "adjustResize" by default in the manifest.
So basically I have native stack (react-navigation):

  1. Screen A (uses , everything works fine);
  2. navigate to Screen B (uses , everything works fine);
  3. navigate back from Screen B to Screen A;
  4. try to focus input -> crash with the log "Can not copy bounds as view is not laid out or attached to window" ;

@4yki
Copy link

4yki commented Sep 26, 2023

the structure of every screen is

<View>
<KeyboardGestureArea>
<ScrollView>
<View ..../>
</ScrollView>
</KeyboardGestureArea>
</View>

@kirillzyusko
Copy link
Owner

Hello @4yki 👋

It's hard to say what is going wrong here because input information is limited. May I kindly ask you to create a new issue and provide a minimal reproduction example?

kirillzyusko added a commit that referenced this issue Nov 16, 2023
## 📜 Description

Removed `isLaidOut` check from `copyBoundsInWindow` method.

## 💡 Motivation and Context

When we are using `native-stack` then on initial mount the view property
`isLaidOut` will be `true`. When we open a new screen and return back to
the previous `isLaidOut` will be `false`.

I've tried to call `invalidate`/`requestLayout`/`forceLayout` methods in
`onAttachedToWindow` method, but it doesn't seem to have any effect at
all.

The I decided to compare how `copyBoundsInWindow` works if `isLaidOut`
check is removed. And turned out there is no difference between two
executions:

|Screen opened first time (isLaidOut check present)|Returned to the
screen (isLaidOut is missing to go to if-statement)|

|---------------------------------------------------|------------------------------------------------------------------|
|<img width="709" alt="Screenshot 2023-11-16 at 17 31 24"
src="https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/8f79bfae-3ed8-4e2c-abb6-a8d6a07eab28">|<img
width="696" alt="Screenshot 2023-11-16 at 17 52 55"
src="https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/4523be4d-36e7-4733-a71f-de7ff0dc5bd1">|

So taking this information into consideration I've decided to remove
that check.

Also for the sake of safety and avoidance of unexpected crashes I
decided to remove `throw Exception` construction and replace it with a
simple logger (since I'm not handling exceptions in my code it's better
to log it).

Closes
#274
#203

## 📢 Changelog

### Android
- removed `isLaidOut` check from `copyBoundsInWindow` method;
- replaced throwing error to logger.

## 🤔 How Has This Been Tested?

Tested on Pixel 7 Pro (android 14).

## 📸 Screenshots (if appropriate):


https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/ef8661da-8a78-4d4a-9362-668365736fed

## 📝 Checklist

- [x] CI successfully passed
@kirillzyusko
Copy link
Owner

@4yki I could reproduce this crash using native-stack navigator. I fixed a problem and published a new 1.9.3 version 👀

@Karthik-B-06
Copy link

Karthik-B-06 commented Jan 12, 2024

It seems like it is still crashing on Android. I am wrapping the FlashList inside KeyboardGestureArea. Using the latest version of package

"react-native-keyboard-controller": "^1.10.1",

@kirillzyusko
Copy link
Owner

kirillzyusko commented Jan 12, 2024

@Karthik-B-06 please, open a new issue and provide minimal reproduction example 🙏

Basically it can not crash with this exception anymore, because I removed throw construction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 android Android specific 🎯 crash Library triggers a crash of the app 👆 interactive keyboard Anything related to interactive keyboard dismissing
Projects
None yet
Development

No branches or pull requests

4 participants