React native bottom tab bar pushing itself up when opening keyboard
Asked Answered
A

15

33

We are using createBottomTabNavigator. In one of the tab contains search bar at the top. While clicking on that search bar, we are opening the keyboard. But the keyboard pushing up the bottom tab bar also. We need the bottom tab bar remains at the bottom when opening keyboard.

  1. One of the solution I have tried is, in android manifest, I have changed android:windowSoftInputMode="adjustPan" or "adjustNothing". It is working fine as expected. But we are using chat layout in another tab which needs "adjustResize". So I have to keep "adjustResize" for windowSoftInputMode.
  2. As another solution, I tried to change windowSoftInputMode inside component itself. SO I have tried with this - https://www.npmjs.com/package/react-native-android-keyboard-adjust. But no use.
  3. As another one, I tried to create a TabBarComponent like mentioned here https://github.com/react-navigation/react-navigation/issues/618. But not working as expected.
const SignedIn = createBottomTabNavigator(
  {
    Followers: {
      screen: FollowerStack,
      ...
    },
    Search: {
      screen: SearchStack,
    },
    Home: {
      screen: HomeStack,
    },
    Bookmarks: {
      screen: BookmarkStack,
    },
    Profile: {
      screen: ProfileStack,
    }
  },
  {
    initialRouteName: "Home",
    tabBarPosition: 'bottom',
    swipeEnabled: false,
    animationEnabled: false,
    tabBarOptions: {
      keyboardHidesTabBar: true,
      showIcon: true,
      showLabel: false,
      activeTintColor: "red",
      inactiveTintColor: "gray",
      adaptive: true,
      safeAreaInset: {
        bottom: "always"
      },
      style: {
        position: 'relative',
        backgroundColor: "#F9F8FB",
        height: TAB_NAVIGATOR_DYNAMIC_HEIGHT,
        paddingTop: DeviceInfo.hasNotch() ? "5%" : "0%",
        minHeight: TAB_NAVIGATOR_DYNAMIC_HEIGHT,
        width: '100%',
        bottom: 0
      }
    }
  }
);
  1. Is there any other properties existed for making the bottom tab bar sticky at the bottom? or
  2. Is it possible to change the android manifest windowSoftInputMode from inside component? Please comment below if you required any other code part for reference. Thanks for any help.
Antabuse answered 19/8, 2019 at 9:53 Comment(3)
Do you want the bottom tab bar to remain visible, but below the keyboard, or for the keyboard slide over the top of the tab bar and hide it (i.e. a modal view)?Swaraj
Thanks fo the reply. Any of the solutions is accepted. Yeah I can say, I need to hide the bottom tab bar when keyboard opens.Antabuse
createMaterialBottomTabNavigator from 'react-navigation-material-bottom-tabs' works perfectly. For more info: reactnavigation.org/docs/en/material-bottom-tab-navigator.htmlRunofthemill
D
53

I used React navigation 5, is this what you want?

<SignedIn.Navigator 
   tabBarOptions={{
      keyboardHidesTabBar: true
   }}         
}>
</SignedIn.Navigator>

The document to read here.

Update: In navigation 6.x its now tabBarHideOnKeyboard

<SignedIn.Navigator 
   tabBarOptions={{
       tabBarHideOnKeyboard: true,
   }}         
}>
</SignedIn.Navigator>
Doubletime answered 16/6, 2020 at 7:13 Comment(4)
It works with the default tabBar but when I provide my own tabBar (i.e.do something like this: tabBar={(props) => <MyTabBar {...props} />), it does not work. Any solutions for that?Smell
@AminDannak can you give more details about your own customization tab bar?Doubletime
@Pok something like this: dev.to/baptistearnaud/…Smell
@AminDannak can you share a snippet of your source code, I can't debug your code just by knowing a few pieces of your code lines.Doubletime
C
30

Please use this on

<Tab.Navigator
screenOptions={{
    tabBarHideOnKeyboard: true
 }}
/>

I am sure it will work perfectly

Conjunct answered 22/11, 2021 at 14:7 Comment(5)
tabBarHideOnKeyboard: true use this in <Tab.Naviagator ScreenOptions={{ tabBarHideOnKeyboard: true}}/>Conjunct
You can use edit link below your post to change or update your answerSomersault
This is the correct option for React Navigation v6.xShowy
That was useful to avoid the double tapping!Slesvig
this didn't work for me, tabar still go over keyboard on android THEN hideSarre
H
13

Found it, just add your bottom navigation into a view making that view of dimensions of the screen, this way:

import React from 'react'
import { StyleSheet, Text, View, Dimensions } from 'react-native'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const { width, height } = Dimensions.get("window")
const Tab = createBottomTabNavigator()

export default function () {
    return (
        <View style={{
            width,
            height,
        }}>
            <Tab.Navigator>
                <Tab.Screen
                    name="Screen1"
                    component={Component}
                />
                <Tab.Screen
                    name="Screen2"
                    component={Component}
                />
                <Tab.Screen
                    name="Screen3"
                    component={Component}
                />
            </Tab.Navigator>
        </View>
    )
}

Hanny answered 4/11, 2021 at 17:48 Comment(2)
No! problem still exists but rare. :(Embroil
I think this probably works because the screen's outermost container was using flex: 1, which resizes to accommodate the keyboard. In that case, it is not that the keyboard is pushing up the tab bar, it is that it is shrinking the container, and the tab bar is being pulled up with the bottom. When you set the height explicitly to the screen height, this resizing of the container doesn't happen.Handset
A
12

Just go to AndroidManifest.xml file and change/add inside activity tag:

android:windowSoftInputMode="adjustPan"
Authorship answered 19/8, 2019 at 10:1 Comment(3)
We have tried. It is working fine. But we have to use "adjustResize", because we are using chat layout in another tab. If I use "adjustPan", In the chat layout page, the whole view pushing up even with the header. So we have to use "adjustResize". Is there any other solutions? If we can contact you privately please provide your contact on any social mediaAntabuse
what about android:windowSoftInputMode="adjustPan|adjustResize" in your case?Authorship
In this case, it is taking the behaviour of "adjustPan" only. Only with "adjustPan" and "adjustPan|adjustResize" both are giving "adjustPan" behaviour only.Antabuse
N
5
screenOptions={{
          headerShown: false,
          tabBarActiveTintColor: '#1a3c43',
          tabBarInactiveTintColor: '#1a3c43',
          tabBarActiveBackgroundColor: 'white',
          tabBarInactiveBackgroundColor: '#1a3c43',
         
          tabBarHideOnKeyboard: true,
   
          tabBarstyle: {
              backgroundColor: '#1a3c43',
              paddingBottom: 3
          }
      }}
Narco answered 15/8, 2022 at 11:40 Comment(0)
S
5

Add below code in AndroidManifest.xml

android\app\src\main\AndroidManifest.xml

<application
      <!--//......-->
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
         <!-- android:windowSoftInputMode="adjustResize" Change to the following -->       
        android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

Run this command inside android folder

cd android && ./gradlew clean

and make build again

npx react-native run-android

Stagy answered 13/3, 2023 at 7:7 Comment(0)
C
4

I was having the exact same issue. Following are the two ways I successfully tackled it.

  1. adding "softwareKeyboardLayoutMode":"pan" to the app.json like below
"android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#FFFFFF"
      },
      "softwareKeyboardLayoutMode":"pan"
    }

by doing this, the bottom navigator was staying hidden behind the keyboard. however, the ScrollView containing TextInputs was not working the way I wanted it to. the whole app screen was getting translated by the height of the keyboard, hiding half of my ScrollView and everything above it (Header and stuff).

  1. The second workaround I used is using useKeyboard hook. step 1: remove "softwareKeyboardLayoutMode" so that it defaults to height (this causes the CustomBottomTabNav to rise above the keyboard as the whole screen gets squeezed in the remaining height) step 2: dynamically reset the position of CustomBottomTabNav when the keyboard is active.

In the screen containing TextInputs

<ScrollView style={{ height: keyboard.keyboardShown? 510 - keyboard.keyboardHeight: 510}}>
/* lots of text inputs*/
</ScrollView>

In the CustomBottomTabNav

tabBarOptions={{
    ...otherStuff,
    style={{ bottom: keyboard.keyboardShown? -100: -10, ...otherStuff}}
}}

This second method is working much more reliably. I tried keyboardAvoidingView but was unable to wrap my head around its unpredictable behavior.

Cuff answered 29/3, 2021 at 19:8 Comment(2)
I understand that it has been 1 year+ since this question was asked, but I'm answering for future devs having similar issueCuff
This is better than the screenOptions way because there isn't an awkward animation transitionMinier
L
1

<Tab.Navigator screenOptions={{ tabBarHideOnKeyboard: Platform.OS!== 'ios'}}>

</Tab.Navigator>

It will work perfectly for both platforms in react native

Laryssa answered 24/8, 2022 at 4:35 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Altigraph
S
1

I doubt this question is ever going to be closed but in case someone stumbles over this problem and needs an answer, I'd recommend looking through the following thread:

https://github.com/react-navigation/react-navigation/issues/6700

Tl;Dr When supplying the framework with a custom navbar, you have to take care of the hiding of the said bar on keyboard opening. This is because it is the default android behaviour.

So either change the manifest configuration as the author already described as his first solution that didn't work.

OR modify your component to listen to the react-natives KEYBOARD. keyboardDidShow & keyboardDidHide Events and either move it down with bottomMargin: -XYZ or hide it completely with a flag.

following two responses on github helped me:

https://github.com/react-navigation/react-navigation/issues/6700#issuecomment-625985764

https://github.com/react-navigation/react-navigation/issues/618#issuecomment-303975621

In case someone wnats to use my code as a reference

interface BottomTabStateProps {
// unrelated Props
}

interface BottomTabDispatchProps {
// unrelated service dispatchers
}

interface BottomTabState {
    navVisible: boolean;
}

class BottomTabContainerClass extends React.Component<
    BottomTabStateProps & BottomTabDispatchProps & NavigationInjectedProps, BottomTabState
> {

    constructor(props: BottomTabStateProps & BottomTabDispatchProps & NavigationInjectedProps) {
        super(props);

        this.state = {
        navVisible: true
        };
    }

    componentDidMount() {
        Keyboard.addListener('keyboardDidShow', () => this.keyboardDidShow());
        Keyboard.addListener('keyboardDidHide', () => this.keyboardDidHide());
    }

    componentWillUnmount() {
        Keyboard.removeAllListeners('keyboardDidShow');
        Keyboard.removeAllListeners('keyboardDidHide');
    }


    keyboardDidShow() {
        this.setState({ navVisible: false });
    }

    keyboardDidHide() {
        this.setState({ navVisible: true });
    }

    render() {

        return (
            <View>
                {
                    this.state.navVisible &&
                    <View>
                          // add custom Navbar here
                    </View>
                }
            </View>
        );
    }
}
Shortlived answered 1/9, 2022 at 13:1 Comment(0)
A
0

I got solution for this problem. Previously, I have done a minor mistake while configuring 'react-native-android-keyboard-adjust'. Now it is working fine. So we can change the 'windowSoftInputMode' for a particular component using this library - https://www.npmjs.com/package/react-native-android-keyboard-adjust

Antabuse answered 19/8, 2019 at 11:45 Comment(0)
P
0

If you are using a TextInput in the search bar you could hide the bottom tab when TextInput is focused (and the keyboard shows) like so:

const [searchBarFocused, setSearchBarFocused] = useState(false)

In the markup:

<TextInput
onFocus = {()=> setSearchBarFocused(true)}
onBlur = {()=> setSearchBarFocused(false)}
 /> 

//Other code

{!searchBarFocused && <CustomBottomTab/>}

For finegrained control put a ref on the textInput to blur/focus and what not programmatically.

Also, you can check out RN:s KeyboardAvoidingView

Palace answered 15/3, 2022 at 11:16 Comment(0)
A
0

My solution: I use android:windowSoftInputMode="adjustResize" (see AndroidManifest.xml) to bring expected behavior, but in some cases, I don't want the keyboard to push the view up when it appears. To avoid the keyboard pushing the whole tab bar and swiper up, I prevent view resizing by giving it a fixed height and width.

On TabBar navigator:

const { height, width } = useWindowDimensions();
const [isPreventResizing, setPreventResizing] = useState(false);

useEffect(() => {
   SharedEventEmitter.addListener(ON_PREVENT_ADJUST_RESIZING, (payload: boolean) => {
      const isPrevent = Platform.OS === 'android' && payload;
      setPreventAdjustResizing(isPrevent);
   });

return SharedEventEmitter.remove;
}, [])

return (
   <View style={isPreventResizing ? { height, width } : { flex: 1 }}>
    <Tab.Navigator>
      <Tab.Screen name={'Home'} component={HomeScreen} />
      <Tab.Screen name={'Chat'} component={ChatScreen} />
      <Tab.Screen name={'Profile'} component={ProfileScreen} />
    </Tab.Navigator>
   </View>
);

On Chat screen:

useLayoutEffect(() => {
    SharedEventEmitter.emit(ON_PREVENT_ADJUST_RESIZING, true);

    return () => SharedEventEmitter.emit(ON_PREVENT_ADJUST_RESIZING, false);
}, []);
Appendicle answered 23/8, 2023 at 16:31 Comment(0)
H
0

To expand on mateo delat's answer, you can prevent the keyboard from pushing up items by setting the height of the screen explicitly to the display height (e.g., by using height from React Native's useWindowDimensions() hook). The tab screens outermost view was probably using flex: 1, which fills the screen but shrinks to accommodate the keyboard. So it is not that the keyboard is pushing up the tab bar, it is that the keyboard is shrinking the container from the bottom up, and the tab bar is being pulled up with it.

Also, I may have this detail wrong, but it seems you need to set the height of the outermost View. So the outermost view of a drawer, of a tab view, of a screen, etc should be set to the windowHeight. It looks like you can set intervening views to flex without issue.

Handset answered 18/2 at 18:26 Comment(0)
S
0

check that you didn't have added keyboardVerticalOffset for KeyboardAvoidingView

after this change, my problem get solve

<KeyboardAvoidingView
    // keyboardVerticalOffset={50}
    behavior={Platform.OS == "ios" ? "height": "height"}
    style={[styles.screenstyle, this.props.styles]}>
    {...}
</KeyboardAvoidingView>
Sibert answered 17/6 at 4:9 Comment(0)
A
-1

For me this package was the solution, you can change the windowSoftInputMode as you need inside a react component.

https://www.npmjs.com/package/react-native-android-keyboard-adjust

Abracadabra answered 24/3, 2023 at 19:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.