0

Need to have a layout where I have a vertically aligned text in the center and button at the right bottom:

example

NOTE: The text should be vertically aligned inside the whole viewport - from top to bttom - like for example the button has an absolute position and is out of the flow (prever to avoid using absolute positioning) https://i.stack.imgur.com/7omuN.jpg

Tried flexDirection: "column" and alignItems: "center" for the container and marginTop: "auto" for the button but this only pushes button at the bottom

Some experiments with the other direction: https://snack.expo.io/Bybw8xsXS

    <View style={styles.container}>
      <Text style={styles.text}>
        Change code in the editor and watch it change on your phone! Save to get
        a shareable url.
      </Text>
      <View style={styles.buttonContainer}>
        <View style={styles.button} />
      </View>
    </View>
  container: {
    marginTop: 80,
    height: 250,
    borderColor: 'red',
    borderWidth: 1,
    // flex: 1,
    flexDirection: 'row',
    // alignItems: 'center',
    alignContent: 'center',
    flexWrap: 'wrap',
  },
  text: {
    fontSize: 18,
    borderWidth: 1,
    borderColor: 'green',
  },
  buttonContainer: {
    width: '100%',
    borderWidth: 1,
    borderColor: 'purple',
    alignSelf: 'flex-end',
  },
  button: {
    borderRadius: 10,
    width: 50,
    height: 25,
    backgroundColor: 'pink',
    alignSelf: 'flex-end',
  }

Leaving this here: React-Native Flexbox - Position One Item at Vertical Center and other at Bottom

pollx
  • 643
  • 9
  • 21

3 Answers3

1

It is better that you use flex. In fact, Flexbox is designed to provide a consistent layout on different screen sizes. For more information: https://facebook.github.io/react-native/docs/flexbox

Just use put you code like this:

<View style={styles.mainContainer}>
    <View style={styles.container}>
    <Text style={styles.text}>
        Change code in the editor and watch it change on your phone! Save to get a shareable url.
    </Text>
    <View style={styles.buttonContainer}>
        <View style={styles.button} />
    </View>
    </View>
</View>

in your styles use:

 mainContainer: {
        flex: 1,
        borderColor: 'red',
        borderWidth: 1,
        alignItems: 'center',
        justifyContent: 'center',
      },
    container: {
        flex: 6,//you can increase it to increase the space
        //borderColor: 'red',
        //borderWidth: 1,
        alignItems: 'center',
        justifyContent: 'center',
      },
      text: {
        fontSize: 18,
        borderWidth: 1,
        borderColor: 'green',
      },
      buttonContainer: {
        flex:1
        width: '100%',
        //borderWidth: 1,
        //borderColor: 'purple',
        justifyContent: 'flex-end',
        alignItems: 'flex-end',
      },
      button: {
        borderRadius: 10,
        width: 50,
        height: 25,
        backgroundColor: 'pink',
        alignSelf: 'flex-end',
      }

I hope I could help.

Saeid
  • 1,996
  • 4
  • 27
  • 44
0

It's super simple: Just nest the text inside another View like this:

const App = () => {
  return (
    <View style={styles.container}>
      <View style={styles.textView}>
        <Text style={styles.text}>
          Change code in the editor and watch it change on your phone! Save to get
          a shareable url.
        </Text>
      </View>
      <View
        style={{
          width: '100%',
          borderWidth: 1,
          borderColor: 'purple',
          alignSelf: 'flex-end',
        }}>
        <View style={styles.button} />
      </View>
    </View>
  );
};

And then update the style:

  container: {
    marginTop: 80,
    height: 250,
    borderColor: 'red',
    borderWidth: 1,
    flex: 1,
    flexWrap: 'wrap',
  },
  textView:{
    flex: 1,
    width: '100%',
    justifyContent: 'center',
    borderColor: 'orange',
    borderWidth:1,
  },
Nikola Diklich
  • 409
  • 1
  • 7
  • 15
  • This code is not working in all device with different size. You should use flex view every where! – Saeid Aug 09 '19 at 14:18
  • I don't understand what you're trying to say. Every view is flexDirection: 'column' by default, and besides, they are width: '100%' – Nikola Diklich Aug 09 '19 at 14:21
  • hey @NikolaDiklic, thanks for the reply ! Your solution vertically aligns the text inside the textView. What I need is the tex to be vertically aligned inside the container (something like taking the button's height out of the flow, but i prefer to avoid absolute positioning) Take a look: https://imgur.com/RPhHrdM – pollx Aug 09 '19 at 17:49
  • @pollx The only workaround would be to add paddingTop, marginTop or an empty view at the top of the container with the same fixed height as the button's view – Nikola Diklich Aug 11 '19 at 14:40
0

If you want to reproduce your mockup, you should use flexbox and wrap your text component and your button component in 2 separate containers :

You text container will have flex 1 and the button container will have no flex. So the text component will take all the space available minus the space taken by the button component.

Update

And to vertically center text in the main container, the only solution I see is to make the button container "absolute"

  <View style={styles.mainContainer}>
    <View style={styles.textContainer}>
      <Text style={styles.text}>
        Change code in the editor and watch it change on your phone! Save to
        get a shareable url.
      </Text>
    </View>
    <View style={styles.buttonContainer}>
      <View style={styles.button} />
    </View>
  </View>

  mainContainer: {
    marginTop: 200,
    width: "100%",
    alignItems: "center",
    justifyContent: "center",
    borderColor: "red",
    borderWidth: 1,
    height: 300
  },
  textContainer: {
    flex: 1,
    width: "100%",
    alignItems: "center",
    justifyContent: "center",
    borderWidth: 1,
    borderColor: "blue"
  },
  text: {
    fontSize: 18,
    borderWidth: 1,
    borderColor: "purple"
  },
  buttonContainer: {
    position: "absolute",
    bottom: 0,
    width: "100%",
    justifyContent: "flex-end",
    alignItems: "flex-end",
    borderWidth: 1,
    borderColor: "green"
  },
  button: {
    borderRadius: 10,
    width: 50,
    height: 25,
    backgroundColor: "blue",
    alignItems: "flex-end"
  }

enter image description here

rphlmr
  • 838
  • 6
  • 12
  • hey @rphlmr, the text is vertically aligned inside the textContainer. What I need is the tex to be vertically aligned inside the mainContainer. Take a look at this: imgur.com/RPhHrdM – pollx Aug 09 '19 at 18:02
  • Indeed what I'm trying to achieve. The only problem I face is that sometimes the text is not 2 lines but 20 and since the button is tall and short the text happens to overlap it - and it bugs me (aaand the designer) out - that's why I prefer to avoid the absolute positioning and was looking for a solution that might respect somehow the spaces between the text container and button container :( – pollx Aug 09 '19 at 18:43
  • try adding a padding (top and bottom) to your text container. Size off padding should be enough to not recover the button container if text grow. – rphlmr Aug 09 '19 at 18:48