Search code examples
cssreact-nativeflexboxposition

Flexbox in react native : How to align 2 items at the center of the screen?


I discovered flexbox recently and I'm struggling to make it work, I'm surely missed some concept that make me hard time to understands it's mechanics so here is what I have:

It's a preview camera screen

  • with a back button on the top right
  • A text in the middle
  • and a record button to shoot some images

Here is what I have at the moment:

enter image description here

this is done with this React native component (style included)

import React from "react";
import { RNCamera } from "react-native-camera";
import { StyleSheet, TouchableOpacity, View, Platform} from "react-native";
import {Icon, Text} from "native-base";
import RequestPermissions from "../components/Permissions/RequestPermissions";
import I18n from "../i18n/i18n";

/**
 * This is the component which allows the user to film his own film
 */
export default class CameraScreen extends React.Component
{
  constructor(props) {
    super(props);
    this.camera = null;
  }

  state = {
    isRecording: false,
    iconVid: "record",
    iconMode: null,
    overlay: true
  };

  /**
   * With RNCamera, it seems that permission is always asked to the user... Maybe this code is then irrelevant
   */
  componentWillMount() {
    if (Platform.OS === "android") {
      RequestPermissions().then(() => {
        console.log("granted");
      }).then((err) => {
        console.log(err)
      });
    }
  }

  componentWillUnmount() {
    this.stopRecording();
  };

  stopRecording = () => {
    if (this.camera) {
      this.camera.stopRecording();
      this.setState({
        isRecording: false,
        iconVid: "record"
      });
    }
  };

  renderCamera = () => {
    return (
      <View style={styles.container}>
        <RNCamera
          ref={cam => {
            this.camera = cam;
          }}
          style={styles.preview}
        >
          <View style={styles.controlsContainer}>
            <View style={styles.topRightButton}>
              <TouchableOpacity onPress={() => this.props.navigation.goBack()}>
                <Icon name={"arrow-left"} type={"Feather"} style={styles.iconFurtive}/>
              </TouchableOpacity>
            </View>
            <View style={styles.middleContainer}>
              <Text style={styles.actionText}>{I18n.t("action_text").toUpperCase()}</Text>
            </View>
            <View style={styles.leftContainer}>
              <TouchableOpacity onPress={() => this.recordVideo()}>
                <Icon name={this.state.iconVid} type={"MaterialCommunityIcons"} style={styles.iconCamera}/>
              </TouchableOpacity>
            </View>
          </View>
        </RNCamera>
      </View>
    );
  };

  /**
   * For more options
   * https://github.com/react-native-community/react-native-camera/blob/master/docs/RNCamera.md#recordasyncoptions-promise
   */
  recordVideo = () => {
    if (this.camera) {
        this.setState({ isRecording: true, iconVid: "stop" });
        // Show the overlay
        console.log("Device is Recording");
        this.camera.recordAsync({maxDuration: 15}).then(data => {
            this.stopRecording();

            console.log("Stop Recording");
            console.log(data);
        }).catch((err) => {
          console.log(err);
          this.stopRecording();
        });
    }
  };

  render() {
    return this.renderCamera()
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop:30,
  },
  controlsContainer: {
    flex: 1,
    flexDirection: "column"
  },
  topRightButton: {
    flex: 1,
    justifyContent: 'flex-start',
    alignItems: 'flex-start',
  },
  middleContainer: {
    flex: 0.5,
    justifyContent: 'center',
    alignItems: 'center',
  },
  leftContainer: {
    flex: 0.5,
    justifyContent: 'center',
    alignItems: 'flex-end',
  },
  actionText: {
    color: "#fff",
    fontSize: 72
  },
  preview: {
    flex: 1,
  },
  iconCamera: {
    color: "#ff4459",
    marginBottom: 50,
    padding: 25,
    backgroundColor: "#fff",
    borderRadius: 50,
  },
  iconFurtive: {
    color: "#fff",
    marginTop: 50,
    marginLeft: 50,
  }
});

Here is what I want:

enter image description here

How to do that with flexbox? What am I missing?


Solution

  • Code changed at View with {styles.topRightButton}

    return (
              <View style={styles.container}>
                <RNCamera
                  ref={cam => {
                    this.camera = cam;
                  }}
                  style={styles.preview}
                >
                  <View style={styles.controlsContainer}>
                    <View style={{justifyContent: 'flex-start', alignItems: 'flex-start',}}>
                      <TouchableOpacity onPress={() => this.props.navigation.goBack()}>
                        <Icon name={"arrow-left"} type={"Feather"} style={styles.iconFurtive}/>
                      </TouchableOpacity>
                    </View>
                    <View style={{flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around'}}>
                      <View style ={{height: 50, width: 50, backgroundColor: 'transparent'}} />
                      <Text style={styles.actionText}>{I18n.t("action_text").toUpperCase()}</Text>
                      <TouchableOpacity onPress={() => this.recordVideo()}>
                        <Icon name={this.state.iconVid} type={"MaterialCommunityIcons"}/>
                      </TouchableOpacity>
                    </View>
                  </View>
                </RNCamera>
              </View>
            );