Wingrider33
Wingrider33

Reputation: 15

KeyboardAvoidingView not pushing content up within navigation stack

I am using the KeyboardAvoidingView to push up some text inputs so the user can see what they are typing, but when I started using a navigation stack, it stopped working correctly.

I have tried adding KeyboardVerticalOffset with statusbar height and the padding I have used to center my elements and while it does push up the inputs they are squished and also it pushes up the background. This is my Login screen code, my navigator code and what my hp function does:

import React, { useContext } from 'react';
import {
    StyleSheet,
    KeyboardAvoidingView,
    Platform,
    Text,
    StatusBar,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

import AppContext from '../universal/GlobalContext';
import LoginForm from '../universal/LoginForm';

function Login( props ) {
    const { hp } = useContext(AppContext);
    const STATUSBAR_HEIGHT = StatusBar.currentHeight;

    return (
        <KeyboardAvoidingView
                style={[styles.loginView, { paddingTop: hp(25) - STATUSBAR_HEIGHT } ]}
                behavior='height'
                keyboardVerticalOffset={() => 300}
        >
            <SafeAreaView style={{ flex: 1 }} >
                <Text style={[
                    styles.title, 
                    { fontSize: hp(10, true) / 1.25, marginBottom: hp(2) } ]}
                > 
                    Login 
                </Text>
                <Text style={[styles.subtitle, { fontSize: hp(5, true) / 1.25, marginBottom: hp(2) } ]}>
                    Enter your credentials
                </Text>
                <LoginForm />
            </SafeAreaView>
        </KeyboardAvoidingView>
    )
}

const styles = StyleSheet.create({
    loginView: {
        flex: 1,
        backgroundColor: 'powderblue'
    },
    title: {
        fontWeight: '500',
        alignSelf: 'center',
    },
    subtitle: {
        alignSelf: 'center',
    }
});

export default Login;
import React, { useState, useContext } from 'react';
import { StatusBar } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import Login from './Login';
import HomeNav from './Dashboard/HomeNav';
import AppContext from '../universal/GlobalContext';

const Stack = createNativeStackNavigator();

function Tab( props ) {
    const { isLoggedIn, setIsLoggedIn } = useContext(AppContext);

    return (
        <NavigationContainer>
            <Stack.Navigator screenOptions={{ keyboardHandlingEnabled: false }}>
                {isLoggedIn ? (
                    <Stack.Group>
                        <Stack.Screen name="HomeNav" component={HomeNav} />
                    </Stack.Group>
                ) : (
                    <Stack.Group screenOptions={{ headerShown: false, headerStatusBarHeight: 0 }}>
                        <Stack.Screen name="Login" component={Login} />
                    </Stack.Group>
                )
                }
            </Stack.Navigator>
        </NavigationContainer>
    )
}

export default Tab;
// returns percentage of screen height
  function hp( heightPercent, text ) {
    const elemHeight = typeof heightPercent === 'number' ? heightPercent : parseFloat(heightPercent);
    let tempheight = height;

    // if in portrait mode and percentage is for text size
    if ( text === true && orientation === 'PORTRAIT' ) {
      tempheight = width;
    }

    return PixelRatio.roundToNearestPixel((tempheight - STATUSBAR_HEIGHT) * elemHeight / 100);
  }

Upvotes: 0

Views: 490

Answers (1)

Mahammad Momin
Mahammad Momin

Reputation: 493

you need to create two stack AppStack and AuthStack

import {createStackNavigator} from '@react-navigation/stack';
const Stack = createStackNavigator();

const AppStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home Screen" component={HomeScreen} />
    </Stack.Navigator>
  );
};

const AuthStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Sign In Screen" component={SignInScreen} />
    </Stack.Navigator>
  );
};

// NavigationUtil.js

const NavigationUtil = () => {

  return (
    <NavigationContainer  ref={navigationRef}>
      <Stack.Navigator initialRouteName="SlpashScreen">
        <Stack.Screen
          name="AppStack"
          component={AppStack}
          options={{headerShown: false}}
        />
       <Stack.Screen
          name="AuthStack"
          component={AuthStack}
          options={{headerShown: false}}
        />
        <Stack.Screen
          name="SlpashScreen"
          component={SlpashScreen}
          options={{headerShown: false}}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

//splashscreen.js

const SlpashScreen = ({}) => {
  useFocusEffect(
    React.useCallback(() => {
    const timeoutID = window.setTimeout(() => {
        checkIsRegister();
    }, 3000);

    return () => window.clearTimeout(timeoutID );
    }, []),
  );

  const checkIsRegister =async()=>{
    await AsyncStorage.getItem('@isRegister').then((value)=>{
      const boolValue = JSON.parse(value);
    
      if(boolValue != null){
        navigationRef.current.navigate("AppStack")
      }else{
        navigationRef.current.navigate("AuthStack")
      }
    });
  }
  return (
    <View style={styles.mainContainer}>
        <Image
            source={Images.logo}
            style={{height:450, width:350, resizeMode:'contain'}}
        />
    </View>
  );
};

export default SlpashScreen;

Hop it's working fine

Upvotes: 0

Related Questions