【React Native入門】4-1 レイアウトを考える 基本画面を構成するもの

「React Native入門　掌田 津耶乃著」にて動作確認したコードを逐一まとめた記事です。
基本は自分用のメモですので、動作確認したい場合ご利用ください。
ある程度は1記事を更新していき、セッションが切り替わったら別記事に残していこうと思います。

目次
[ P.150〜P.155 ]
・スマートフォンの画面構成
・ステータスバーとヘッダー
・ステータスバーとヘッダーを表示する
[ P.155〜P.159 ] フレックスボックスについて
[ P.159〜P.162 ] flex属性の働き
[ P.162〜P.165 ] flex:0と1の動き

---

[ P.150〜P.155 ]
・スマートフォンの画面構成
・ステータスバーとヘッダー
・ステータスバーとヘッダーを表示する

[StatusBar コンポーネント]

```
<StatusBar barStyle=タイプ hidden=真偽値 />
```
<タイプ>
default
light-content
dark-content

[Header コンポーネント]

```
<Header
 leftComponent=コンポーネントの設定
 centerComponent=コンポーネントの設定
 rightComponent=コンポーネントの設定
 otherContainerStyles=スタイルの設定
 innerContainerStyles=スタイルの設定
/>
```

```
アイコンの表示
{{ icon: アイコン名,　color: '色',　size: サイズ }}

テキストの表示
{{ text: テキスト, style: スタイル }}
```

```js:App.js
import React, { Component } from 'react';
import { StyleSheet, Alert, StatusBar, TextInput, Text, View } from 'react-native';
import { Header } from 'react-native-elements';

export default class App extends Component {

  constructor(props) {
    super(props);
    this.title = 'Layout';
    this.state = {
      message: 'This is sample message.',
    }
  }

  render() {
    return (
      <View style={styles.body}>
        <StatusBar barStyle="light-content" hidden={ false } />
        <Header
          leftComponent={{
            icon: 'menu', color: 'white', size: 25,
            onPress: this.doActionLeft
          }}
          centerComponent={{
            text: 'Sample App',
            style: styles.header
          }}
          rightComponent={{
            icon: 'android',
            color: 'white',
            size: 25,
            onPress: this.doActionRight
          }}
          otherContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
          innerContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
        />
        <View style={styles.base}>
          <Text style={ styles.title }>{ this.title }</Text>
          <Text style={ styles.message }>{ this.state.message }</Text>
        </View>
      </View>
    );
  }

  doActionLeft = () => { Alert.alert('Left icon tapped!'); }
  doActionRight = () => { Alert.alert('Right icon tapped!'); }
  
}

const styles = StyleSheet.create ({
  body: {
    height: '100%',
    backgroundColor: '#efecea'
  },
  base: {
    padding: 20
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold'
  },
  title: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 25,
  },
  message: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 15, 
  },
});
```

---

[ P.155〜P.159 ] フレックスボックスについて

・flexDirection
　row…横方向
　column…縦方向

・justifyContent
　flex-start…開始位置から並べる
　center…中央に並べる
　flex-end…終了位置から並べる
　space-around…絶対を一定幅ごとに分け、その中心に並べる
　space-between…両端から均等に並べる
　space-evenly…両端から同じ幅でスペースをとって並べる

```js
<View style={{
 flexDirection: '方向',
 justifyContent: '位置揃え',
}}>
 ...配置されるコンポーネント...
</View>
```

```js:App.js
import React, { Component } from 'react';
import { StyleSheet, Alert, StatusBar, TextInput, Text, View } from 'react-native';
import { Header } from 'react-native-elements';

export default class App extends Component {

  constructor(props) {
    super(props);
    this.title = 'FlexLayout';
    this.state = {
      message: 'This is sample message.',
    }
  }

  render() {
    return (
      <View style={styles.body}>
        <StatusBar barStyle="light-content" hidden={ false } />
        <Header
          leftComponent={{
            icon: 'menu', color: 'white', size: 25,
            onPress: this.doActionLeft
          }}
          centerComponent={{
            text: 'Sample App',
            style: styles.header
          }}
          rightComponent={{
            icon: 'android',
            color: 'white',
            size: 25,
            onPress: this.doActionRight
          }}
          otherContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
          innerContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
        />
        <View style={styles.base}>
          <Text style={ styles.title }>{ this.title }</Text>
          <Text style={ styles.message }>{ this.state.message }</Text>
          <View style={{
            flexDirection: 'row',
            justifyContent: 'center',
          }}>
            <View style={ styles.view } />
            <View style={ styles.view } />
            <View style={ styles.view } />
          </View>
        </View>
      </View>
    );
  }

  doActionLeft = () => { Alert.alert('Left icon tapped!'); }
  doActionRight = () => { Alert.alert('Right icon tapped!'); }
  
}

const styles = StyleSheet.create ({
  body: {
    height: '100%',
    backgroundColor: '#efecea'
  },
  base: {
    padding: 5
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold'
  },
  title: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 25,
  },
  message: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 15, 
  },
  view: {
    width: 100,
    height: 100,
    margin: 5,
    backgroundColor: '#6666aa'
  }
});
```

---

[ P.159〜P.162 ] flex属性の働き

コンポーネントのサイズを割合で変えることができ、
よりフレキシブル（変動）なレイアウトが可能。

`flex:整数のみ`　※実数は不可

```js
// 比率1:2のレイアウトの場合
<View style={{ flex:1 }} />
<View style={{ flex:2 }} />

// スタイルシート利用の場合
<View style={ styles.view1 } />
<View style={ styles.view2 } />
...
const styles = StyleSheet.create ({
  view1: {
    flex: 1,
  },
  view2: {
    flex: 2,
  },
});
```

```js:App.js
import React, { Component } from 'react';
import { StyleSheet, Alert, StatusBar, TextInput, Text, View } from 'react-native';
import { Header } from 'react-native-elements';

export default class App extends Component {

  constructor(props) {
    super(props);
    StatusBar.setBarStyle('light-content', true);
    // StatusBar.setBackgroundColor('#008080', true); // Andoroidのみ
    this.title = 'FlexLayout';
    this.state = {
      message: 'This is FlexLayout.',
    }
  }

  render() {
    return (
      <View style={styles.base}>
        <Header
          leftComponent={{
            icon: 'menu', color: 'white', size: 25,
            onPress: this.doActionLeft
          }}
          centerComponent={{
            text: 'Sample App',
            style: styles.header
          }}
          rightComponent={{
            icon: 'android',
            color: 'white',
            size: 25,
            onPress: this.doActionRight
          }}
          otherContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
          innerContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
        />

        <Text style={ styles.title }>{ this.title }</Text>
        <Text style={ styles.message }>{ this.state.message }</Text>

        <View style={styles.container}>
          <View style={ styles.view1 } />
          <View style={ styles.view2 } />
          <View style={ styles.view3 }>
            <View style={ styles.view4 } />
            <View style={ styles.view4 } />
          </View>
        </View>
        
      </View>
    );
  }

  doActionLeft = () => { Alert.alert('Left icon tapped!'); }
  doActionRight = () => { Alert.alert('Right icon tapped!'); }
  
}

const styles = StyleSheet.create ({
  base: {
    flex: 1
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold'
  },
  title: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 25,
  },
  message: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 15, 
  },
  container: {
    flex: 1,
    padding: 10,
    margin: 10,
    backgroundColor: '#eeffee',
    borderStyle: 'solid',
    borderWidth: 2,
    borderColor: 'red',
  },
  view1: {
    flex: 1,
    margin: 5,
    backgroundColor: '#6666aa',
    borderStyle: 'solid',
    borderWidth: 2,
    borderColor: 'black',
  },
  view2: {
    flex: 2,
    margin: 5,
    backgroundColor: '#9999cc',
    borderStyle: 'solid',
    borderWidth: 2,
    borderColor: 'black',
  },
  view3: {
    flex: 2,
    flexDirection: 'row',
    margin: 0,
  },
  view4: {
    flex: 1,
    margin: 5,
    backgroundColor: '#ccccff',
    borderStyle: 'solid',
    borderWidth: 2,
    borderColor: 'blue',
  },
});
```

---

[ P.162〜P.165 ] flex:0と1の動き

※いまいち使い方わからないため動作確認したコードのみアップしておきます。
個人的感想だと上3つをきっちり理解すればLayoutはできそうな感じがします。

```js:App.js
import React, { Component } from 'react';
import { StyleSheet, Alert, StatusBar, TextInput, Text, View } from 'react-native';
import { Header } from 'react-native-elements';

export default class App extends Component {

  constructor(props) {
    super(props);
    StatusBar.setBarStyle('light-content', true);
    // StatusBar.setBackgroundColor('#008080', true); // Andoroidのみ
    this.title = 'FlexLayout';
    this.state = {
      message: 'This is FlexLayout.',
    }
  }

  render() {
    return (
      <View>
        <Header
          leftComponent={{
            icon: 'menu', color: 'white', size: 25,
            onPress: this.doActionLeft
          }}
          centerComponent={{
            text: 'Sample App',
            style: styles.header
          }}
          rightComponent={{
            icon: 'android',
            color: 'white',
            size: 25,
            onPress: this.doActionRight
          }}
          otherContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
          innerContainerStyles={{
            height: 100,
            backgroundColor: '#dd0000'
          }}
        />

        <View style={styles.base}>
          <Text style={ styles.title }>{ this.title }</Text>
          <Text style={ styles.message }>{ this.state.message }</Text>

          <View style={{
            flex: 1,
            flexDirection: 'row',
            justifyContent: 'flex-end',
            alignItems: 'flex-start',
          }}>
            <View style={ styles.view } />
            <View style={ styles.view } />
            <View style={ styles.view } />
          </View>

          <View style={{
            flex: 0,
            flexDirection: 'column',
            justifyContent: 'flex-start',
            alignItems: 'flex-start',
          }}>
            <View style={ styles.view2 } />
            <View style={ styles.view2 } />
          </View>

          <View style={{
            flex: 1,
            flexDirection: 'column',
            justifyContent: 'flex-start',
            alignItems: 'flex-end',
          }}>
            <View style={ styles.view2 } />
            <View style={ styles.view2 } />
          </View>

          <View style={{
            flex: 1,
            flexDirection: 'column',
            justifyContent: 'flex-start',
            alignItems: 'flex-start',
          }}>
            <View style={ styles.view2 } />
            <View style={ styles.view2 } />
          </View>
            
        </View>

      </View>
    );
  }

  doActionLeft = () => { Alert.alert('Left icon tapped!'); }
  doActionRight = () => { Alert.alert('Right icon tapped!'); }
  
}

const styles = StyleSheet.create ({
  base: {
    padding: 5
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold'
  },
  title: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 25,
  },
  message: {
    padding: 10,
    color: '#3a3c49',
    fontSize: 15, 
  },
  view: {
    width: 100,
    height: 100,
    margin: 5,
    backgroundColor: '#6666aa',
  },
  view2: {
    width: 45,
    height: 45,
    margin: 5,
    backgroundColor: '#9999ff',
  },
});
```