#StackBounty: #react-native Vertically center image that's not affected by KeyboardAwareScrollView in React Native

Bounty: 50

Alright, so this has got me busy for quite a few hours already. I am trying to create a login screen where the main components are rendered on the bottom, with the logo in the remaining space. This is kind of what I would like to achieve:

desired result

To support my textinputs, I use KeyboardAwareScrollView, as it works better for me as opposed to KeyboardAvoidingView. My code currently looks like this (I plan on using a background image with a 50% color overlay rather than the red background, so the ImageBackground has to stay in place too):

  <ImageBackground
    source={require('./assets/img/background-clouds.png')}
    resizeMode="cover"
    style={styles.backgroundImage}>
    <View style={styles.backgroundOverlay} />
    <View style={styles.dummyView}>
      <Text>elloha</Text>
    </View>
    <Image
      source={require('./assets/img/logo.png')}
      style={styles.backgroundLogo}
      resizeMode="contain"
    />
    <KeyboardAwareScrollView
      keyboardShouldPersistTaps="always"
      keyboardOpeningTime={0}
      alwaysBounceHorizontal={false}
      alwaysBounceVertical={false}
      contentInsetAdjustmentBehavior="automatic"
      showsHorizontalScrollIndicator={false}
      showsVerticalScrollIndicator={false}
      automaticallyAdjustContentInsets={false}
      extraScrollHeight={30}
      enableOnAndroid>
      <StatusBar
        backgroundColor="transparent"
        barStyle="light-content"
        hidden={false}
        translucent
      />
      <TouchableWithoutFeedback
        onPress={Keyboard.dismiss}
        accessible={false}>
        <View style={styles.content}>
          <View style={styles.backgroundContainer}>
            <SafeAreaView style={{ flex: 0 }} />

            <View style={styles.loginContainer}>
              <View style={styles.loginScreen}>
                // textinputs and buttons go here
              </View>
              <SafeAreaView style={{ backgroundColor: 'white' }} />
            </View>
            <View
              style={{
                backgroundColor: 'white',
                height: Dimensions.get('window').height,
                position: 'absolute',
                width: Dimensions.get('window').width,
                top: Dimensions.get('window').height,
              }}
            />
          </View>
        </View>
      </TouchableWithoutFeedback>
    </KeyboardAwareScrollView>
  </ImageBackground>

Relevant styles:

const styles = StyleSheet.create({
  container: {
    backgroundColor: "white",
  },
  content: {
    flex: 1,
  },
  backgroundImage: {
    flex: 1,
    position: "absolute",
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    width: Dimensions.get("window").width,
    height: Dimensions.get("window").height,
  },
  backgroundContainer: {
    justifyContent: "flex-end",
    flex: 1,
    width: Dimensions.get("window").width,
    height: Dimensions.get("window").height,
  },
  backgroundOverlay: {
    backgroundColor: "red",
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
  },
  logoContainer: {
    top: "10%",
    width: "100%",
  },
  backgroundLogo: {
    alignSelf: "center",
    position: "absolute",
    width: 126,
    height: 96,
  },
  dummyView: {
    backgroundColor: "red",
    flex: 1,
  },
  loginContainer: {
    borderTopEndRadius: 30,
    borderTopStartRadius: 30,
    width: "100%",
    backgroundColor: "white",
    height: 500,
    alignItems: "center",
    paddingTop: Dimensions.get("window").width * 0.1,
  },
  loginScreen: {
    width: "80%",
    backgroundColor: "white",
  },
});

This yields the following result:

current result

I can get it done by adding top: 160 to the backgroundLogo style, but that’s a fixed value. I want it to be always in the center of the available space, but I’m unable to add a view between the background and the loginContainer, as all the logic for the keyboard and such is handled in between.

Is there a way to achieve what I want? Ideally, I should also be able to check the available height, and only show the logo if there is enough space (e.g. available height > 100, otherwise don’t show logo).

Important:
I want the logo to stay fixed, so if the keyboard is shown, the logo should not move up. The loginContainer should go "over" the logo


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.