ReactNativeのFlexboxレイアウト

React Nativeで利用するFlexboxのまとめ。

Flexbox

React Nativeではコンポーネントのレイアウトをflexboxで行います。そもそもFlexboxはCSS3で定義されているレイアウトモードで、スクリーンの空き部分を埋めるように要素を表示します。

A Complete Guide to Flexboxでの解説がわかりやすいです。

Flexboxではコンテナになる要素の主軸の方向を定めることで、子要素がどのような配置になるかが決まります。

以下の様なコンポーネントの構成で、特にレイアウトのスタイルを定義しない場合は、上から順に並びます。

class StopWatch extends Component {  
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.child}>Child</Text>
        <Text style={styles.child}>Child</Text>
        <Text style={styles.child}>Child</Text>
      </View>
    );
  }
}

let styles = StyleSheet.create({  
  container: {
    color: '#3E4242',
    marginTop: 20
  },

  child: {
    borderColor: '#CCC',
    borderWidth: 2,
    padding: 20,
    textAlign:   'center'
  }
});

子要素をflexboxを使ってレイアウトしてみます。各要素に対してflexプロパティをセットします。プロパティにセットするのは数値で、この値が各子要素に割り当てられる「重さ」になります。

let styles = StyleSheet.create({  
  container: {
    //...
    flex: 1
  },

  child: {
    //...
    flex: 1
  }
});

この例では1を指定したので、各要素は均等になります。

一番外側にある.containerビューがflex: 1なので、スクリーン全体に広がり、その中に子要素がflex: 1で均等に配置されるイメージです。

子要素のflexの値を変えるとその値に応じた割合で画面全体に配置されます。

class StopWatch extends Component {  
  render() {
    return (
      <View style={styles.container}>
        <Text style={[styles.child, styles.child1]}>Child</Text>
        <Text style={[styles.child, styles.child2]}>Child</Text>
        <Text style={[styles.child, styles.child3]}>Child</Text>
      </View>
    );
  }
}

let styles = StyleSheet.create({  
  container: {
    // ...
    flex: 1,
  },

  child: {
    // ...
    flex: 1
  },

  child1: { flex: 1 },
  child2: { flex: 2 },
  child3: { flex: 3 }

});

flex-direction

flexはflex-directionプロパティを使用することで、子が並ぶ方向を指定できます。

flexDirectionプロパティをcolumnにすると、子要素が垂直に、rowにすると水平に並びます。

flexWrap

wrapnowrapを指定します。コンテナとなる親要素に子要素が入りきらない場合、単一のラインのまま回りこみをしないか、複数のラインにして回り込みさせるかを指定するものです。

class StopWatch extends Component {  
  render() {
    return (
      <View style={styles.container}>
        <Text style={[styles.child, styles.child1]}>Child</Text>
        <Text style={[styles.child, styles.child2]}>Child</Text>
        <Text style={[styles.child, styles.child3]}>Child</Text>
      </View>
    );
  }
}

let styles = StyleSheet.create({  
  container: {
    backgroundColor: '#3E4242',
    marginTop: 20,
    flexDirection: 'row',
    flexWrap: 'nowrap' // or wrap
  },

  child: {
    borderColor: '#CCC',
    borderWidth: 2,
    color: '#FFF',
    padding: 20,
    textAlign: 'center'
  },

  child1: { width: 300 },
  child2: { width: 200 },
  child3: { width: 100 }

});

alignItems

コンテナになる親要素にalignItemsを指定すると、その子要素は空いたスペースを埋めるように広がらなくなります。flex-start/flex-end/centerを指定し、子要素の揃えを指定します。

alignSelf

親要素で指定されたalignItemsを子要素側で上書きするためのプロパティです。

class StopWatch extends Component {  
  render() {
    return (
      <View style={styles.container}>
        <Text style={[styles.child, styles.child1]}>Child 1</Text>
        <Text style={[styles.child, styles.child2]}>Child 2</Text>
        <Text style={[styles.child, styles.child3]}>Child 3</Text>
      </View>
    );
  }
}

let styles = StyleSheet.create({  
  container: {
    // ...
    flex: 1,
    flexDirection: 'row',
    alignItems: 'flex-start'
  },

  child: {
    // ...
    flex: 1
  },

  child1: { alignSelf: 'center' },
  child2: { alignSelf: 'flex-end' },
  child3: { alignSelf: 'flex-start' }

});