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

Keyboard covers input when inside a react navigation bottom tab navigator #1424

Closed
bobby-white opened this issue Sep 27, 2019 · 21 comments
Closed
Labels

Comments

@bobby-white
Copy link

bobby-white commented Sep 27, 2019

Issue Description

The problem is when Gifted Chat is inside of a bottom tab navigator from react-navigation when I first focus the message box the keyboard covers the text input. Once I type the first letter the text input comes into view with the correct positioning.

This only happens when the GiftedChat component is inside a bottom tab navigator.
Everything works fine when the chat component is inside ONLY a stack navigator.
It breaks again if inside a stack navigator nested inside a tab navigator.

ezgif com-video-to-gif

Steps to Reproduce / Code Snippets

import { View } from 'react-native';
import { GiftedChat } from 'react-native-gifted-chat';
import { createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';

function ThreadScreen() {
  return (
    <View style={{ flex: 1, backgroundColor: 'red' }}>
      <GiftedChat
        messages={[]}
        user={{
          _id: 1,
        }}
        onSend={() => {}}
      />
    </View>
  );
}

const Navigator = createAppContainer(
  createBottomTabNavigator({
    Thread: {
      screen: ThreadScreen,
    },
  })
);

function App() {
  return <Navigator />;
}

export default App;

Expected Results

The input should not be covered by keyboard on focus.

Additional Information

  • Nodejs version: 8.16.1
  • React version: 16.9.0
  • React Native version: 0.61.1
  • react-native-gifted-chat version: 0.10.1
  • Platform(s) (iOS, Android, or both?): iOS
@bobby-white bobby-white changed the title Keyboard covers input when inside a react navigation tab navigator Keyboard covers input when inside a react navigation bottom tab navigator Sep 27, 2019
@riguy14
Copy link

riguy14 commented Sep 30, 2019

Same issue here. Tried all sorts of different things with KeyboardAvoidingView (with each different behaviour and with/without { flex: 1}), and tried react-native-keyboard-aware-scroll-view.

Only thing I found that has helped somewhat is setting tabBarOptions: { keyboardHidesTabBar: !(Platform.OS === 'ios') } on the createBottomTabNavigator. This leads to its own issue of a gap between the keyboard and the text input on iOS, but it's the best I could get. Working on simulators and in Expo on physical devices.

Btw, this issue is similar to #1272.

@bobby-white
Copy link
Author

I was able to fix the issue and close the gap with the following:
Has only been tested on iPhone 11 simulator, will test more later today.

<GiftedChat
  bottomOffset={83}
  ...
/>

and

tabBarOptions: {
  keyboardHidesTabBar: !(Platform.OS === 'ios')
}

@riguy14
Copy link

riguy14 commented Oct 1, 2019

Yeah I did the same, but that number is good for only a subset of phones. Once you switch to something like an iPad that distance is different and it cuts off half the input. I tried to look into measuring the distance from the bottom dynamically, but there was nothing obvious on react-navigation to do so (discussion about it here https://github.com/react-navigation/tabs/issues/97).

Ended up just setting the background to the same color as the input so the extra height didn't look weird. Will circle back to calculating the height when I have some time, or hopefully they realize this a pretty common use case (chat inside a stack inside tabs).

@partiellkorrekt
Copy link

I am measuring the height of the Bottom TabBar in the following way:

Add hooks to the render-function:

const [bottomOffset, setBottomOffset] = useState(0)
const wrapper = useRef<View>()
const handleLayout = useCallback(() => {
  wrapper.current && wrapper.current.measureInWindow((_x: number, y: number, _width: number, height: number): void => {
    const nextBottomOffset = Dimensions.get('window').height - y - height
    setBottomOffset(nextBottomOffset)
  })
}, [])

And then wrap GiftedChat like this:

<View style={{ flex: 1 }} onLayout={handleLayout} ref={wrapper}>
  <GiftedChat
    bottomOffset={bottomOffset}
    {...chatProps}
  />
</View>

@mkhoussid
Copy link

mkhoussid commented Oct 23, 2019

Was this resolved? I am also using React Navigation, but I cant get the TextInput to move up with the keyboard. I've gone in and changed the SafeAreaView into KeyboardAvoidingView, that didn't work for me. Is this truly a React Navigation issue?

Edit: I managed to get the keyboard to pop up with forceGetKeyboardHeight, but still covering the text input.

@ian
Copy link

ian commented Oct 26, 2019

Can confirm this is still an issue with iOS / Expo / gifted chat 0.11.3. Works fine after you start typing but the input is definitely hidden when the keyboard loads initially.

@Ares513
Copy link

Ares513 commented Oct 28, 2019

I am having the same issue, does anyone have an example of a working keyboardavoidingview with Expo?

@mkhoussid
Copy link

I am having the same issue, does anyone have an example of a working keyboardavoidingview with Expo?

https://stackoverflow.com/a/54678123/2891356

@ian
Copy link

ian commented Oct 28, 2019

@mkhoussid adding a <KeyboardSpacer/> is not the correct solution. gifted-chat already includes a keyboard spacer inside its inner workings plus this causes a large padding on the input after focus.

This seems to be a focus issue on iOS, the best hack solution I've come up with is to patch into the keyboard show/hide events and then force a toolbar reset, but this isn't as smooth as a native experience should be.

We need a proper bug fix on this.

componentWillMount() {
  if (Platform.OS === "ios") {
    this.keyboardDidShowListener = Keyboard.addListener(
      "keyboardDidShow",
      this._keyboardDidShow,
    )
    this.keyboardDidHideListener = Keyboard.addListener(
      "keyboardDidHide",
      this._keyboardDidHide,
    )
  }
}

componentWillUnmount() {
  if (Platform.OS === "ios") {
    this.keyboardDidShowListener.remove()
    this.keyboardDidHideListener.remove()
  }
}

_keyboardDidShow = e => {
  setTimeout(() => this.gifted.resetInputToolbar(), 50)
}

@mkhoussid
Copy link

mkhoussid commented Oct 28, 2019

@ian No, it's an issue for both mobile OS'. And the linked solution worked just fine for me. Perhaps something else is wrong with your code. Other people experiencing this should try it, not much to lose.

Also, try converting your component to a functional component. I've ran into inexplicable issues with class based components in the past, that I couldn't reproduce with functional components.

@ian
Copy link

ian commented Oct 28, 2019

@mkhoussid Android working fine, this seems to be an iOS specific issue.

This issue is specific to gifted chat when used with react-navigation, specifically createBottomTabNavigator. Are you using all of the above?

@mkhoussid
Copy link

@ian Yeah, and it was broken on both for me. It's a bug either way, with and without createBottomTabNavigator. The TextInput was being covered by the keyboard, confirmed on physical devices

@Ares513
Copy link

Ares513 commented Oct 31, 2019

I found this solution that does actually work all the way, at least for me, based on this:
https://stackoverflow.com/questions/58606815/issue-with-gifted-chat-the-messages-jump-up-the-screen-on-text-input

            <KeyboardAvoidingView
                style={{ flex: 1 }}
                behavior="padding"
                keyboardVerticalOffset={Platform.select({
                    ios: () => 0,
                    android: () => 100
                })()}
            >
            <GiftedChat
                isAnimated
                scrollToBottom
                onSend={(messages) => Fire.shared.send(messages, this.state.conversationId)}
                ref={this.gifted}
                messages={this.state.messages}
                user={this.user}
            />
            </KeyboardAvoidingView>

EDIT: the bottom solution was incomplete for me, leaving it for posterity

I found a temporary solution to this:, react-native-keyboard-spacer:
https://github.com/Andr3wHur5t/react-native-keyboard-spacer

            <View style={{width: '100%', height: '100%'}}>
                <GiftedChat
                    messages={this.state.messages}
                    onSend={(messages) => Fire.shared.send(messages, this.state.conversationId)}
                    user={this.user}
                    bottomOffset={83}
                    ref={this.gifted}
                />
                <KeyboardSpacer/>
            </View>

@neto15cg
Copy link

I found this solution that does actually work all the way, at least for me, based on this:
https://stackoverflow.com/questions/58606815/issue-with-gifted-chat-the-messages-jump-up-the-screen-on-text-input

            <KeyboardAvoidingView
                style={{ flex: 1 }}
                behavior="padding"
                keyboardVerticalOffset={Platform.select({
                    ios: () => 0,
                    android: () => 100
                })()}
            >
            <GiftedChat
                isAnimated
                scrollToBottom
                onSend={(messages) => Fire.shared.send(messages, this.state.conversationId)}
                ref={this.gifted}
                messages={this.state.messages}
                user={this.user}
            />
            </KeyboardAvoidingView>

EDIT: the bottom solution was incomplete for me, leaving it for posterity

I found a temporary solution to this:, react-native-keyboard-spacer:
https://github.com/Andr3wHur5t/react-native-keyboard-spacer

            <View style={{width: '100%', height: '100%'}}>
                <GiftedChat
                    messages={this.state.messages}
                    onSend={(messages) => Fire.shared.send(messages, this.state.conversationId)}
                    user={this.user}
                    bottomOffset={83}
                    ref={this.gifted}
                />
                <KeyboardSpacer/>
            </View>

For me, i needed changed behavior="padding" to behavior="height".

@rhdeck
Copy link

rhdeck commented Dec 2, 2019

I was able to address the symptoms by applying keyboardHidesTabBar: false to the second argument of createMaterialBottomTabNavigator. (It wasn't documented, but it works!)

@victors1681
Copy link

I had this issue when I had a bottomTabNavigation my workflow was HomeChat (with bottom tab) after select single user hide the bottomTabNavigation and everything started working fine.

code to hide

const ChatStack = createStackNavigator(
  {
    ChatHome: ChatHomeScreen,
    ChatRoom: ChatScreen, 
  },
  config,
);

ChatStack.navigationOptions = ({navigation}) => {
  let tabBarVisible = true;
  if (navigation.state.index > 0) {
    tabBarVisible = false;
  }

  return {
    tabBarVisible,
    title: 'Chat',
    tabBarLabel: 'Chat',
    tabBarIcon: ({focused}) => <TabBarIcon focused={focused} name="forum" />,
  };
};

@dcangulo
Copy link

dcangulo commented Jan 10, 2020

Just like the other solution, what worked for me was the following:

  • Adding keyboardHidesTabBar: false to tabBarOptions.
  • Adding bottomOffset={83} (tested on iPhone 11 Pro Max).
  • or addingbottomOffset={48} (tested on iPhone 8 Plus) prop on GiftedChat component.
  • To support both, I used react-native-device-info to detect if the phone have notch and come up with bottomOffset={DeviceInfo.hasNotch() ? 83 : 48}.

My target is iOS only I don't know if the code above has a breaking effect on Android.

@stale
Copy link

stale bot commented Feb 9, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Feb 9, 2020
@stale stale bot closed this as completed Feb 14, 2020
@woodcockjosh
Copy link

/reopen

@fukemy
Copy link

fukemy commented Apr 17, 2022

I am measuring the height of the Bottom TabBar in the following way:

Add hooks to the render-function:

const [bottomOffset, setBottomOffset] = useState(0)
const wrapper = useRef<View>()
const handleLayout = useCallback(() => {
  wrapper.current && wrapper.current.measureInWindow((_x: number, y: number, _width: number, height: number): void => {
    const nextBottomOffset = Dimensions.get('window').height - y - height
    setBottomOffset(nextBottomOffset)
  })
}, [])

And then wrap GiftedChat like this:

<View style={{ flex: 1 }} onLayout={handleLayout} ref={wrapper}>
  <GiftedChat
    bottomOffset={bottomOffset}
    {...chatProps}
  />
</View>

only this solution work for me

@Michaelrecycle
Copy link

Michaelrecycle commented May 1, 2022

I might have a solution for you, first I'll go over of what I tried. Since I am also using the tab navigation (but I am setting these settings tabBarVisible & keyboardHidesTabBar to false, the keyboard still blocked the input on Android (on ios I just had to make bottomOffset 0 and it worked on smaller screens). I've tried KeyboardAvoidingView and the KeyboardSpacer methods but both resulted in text input occupying a massive amount of space when focused and before typing. Instead I did this which fixed it for me:

<GiftedChat
  ...
  textInputProps={inputOverrides}
/>

Where:

  const inputOverrides = {
    autoCorrect: false,
    multiline: true,
  };
  if (Platform.OS === "android") {
    inputOverrides.style = {
      paddingBottom: 20,
      paddingTop: 5,
      paddingHorizontal: 10,
      width: "90%",
    };
  }

Tested with emulators and physical devices and seems to work fine!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests