【React Native入門】4-3 レイアウトを考える モーダル

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

目次
[ P.178〜P.182 ] モーダルとは？
[ P.182〜P.186 ] よりモーダルらしく

---

[ P.178〜P.182 ] モーダルとは？

```js
<Modal
 animationType="slide" // fade,node
 transparent={ false } // trueにすると下の画面が見える
 visible={ false } // モーダル非表示
 onRequestClose={ this.closeModal } // なぜか入れなくても動く ？
>
...モーダル表示...
</Modal>
```

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

export default class App extends Component {

  items = ['one','two','three','four','five','six','seven','eight','nine','ten'];

  constructor(props) {
    super(props);
    StatusBar.setBarStyle('light-content', true);
    // StatusBar.setBackgroundColor('#008080', true); // Androidのみ
    this.title = 'Modal Layout';
    this.state = {
      message: 'This is ModalLayout.',
      modal: false
    }
  }

  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'
          }}
        />
        <View style={ styles.body }>
          <Text style={ styles.title }>{ this.title }</Text>
          <Text style={ styles.message }>{ this.state.message }</Text>

          <Modal
            animationType="slide"
            transparent={ false }
            visible={ this.state.modal }
            onRequestClose={ this.closeModal } // 入れなくても動く ?
          >
            <View style={{ padding: 25 }}>
              <Text style={ styles.modalTitle }>Modal View</Text>
              <Text style={ styles.modalContent }>モーダル表示です</Text>
              <Button title="Close" onPress={ this.doModalAction } />
            </View>
          </Modal>

          <View style={{ padding: 10 }}>
            <Button title="Click" onPress={ this.doAction } />
          </View>
        </View>

      </View>
    );
  }

  doAction = () => {
    this.setState({ modal: true });
  }
  doModalAction = () => {
    this.setState({
      modal: false,
      message: 'モーダルを閉じました'
    });
  }

  // 入れなくても動く ?
  closeModal = () => {
    alert('Close Modal');
    this.setState({ modal: false });
  }

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

const styles = StyleSheet.create ({
  base: {
    padding: 0, 
    flex:1
  },
  body: {
    padding: 10, 
    flex:1
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold'
  },
  title: {
    textAlign: "center",
    paddingTop: 20,
    paddingBottom: 10,
    fontSize: 25,
  },
  message: {
    textAlign: "center",
    paddingBottom: 10,
    fontSize: 15,
  },
  modalTitle: {
    textAlign: "center",
    paddingTop: 20,
    paddingBottom: 10,
    fontSize: 25,
  },
  modalContent: {
    textAlign: "center",
    paddingBottom: 10,
    fontSize: 15,
  }
});
```

---

[ P.182〜P.186 ] よりモーダルらしく

```js
<Modal
 animationType="fade" // fadeに変更
 transparent={ true } // trueに変更
 visible={ this.state.modal } // 変更なし
 onRequestClose={ this.closeModal } // 変更なし
>
<View style=グレーで透過させるスタイル>
 <View style=パネル背景のスタイル>
  ...表示されるところ...
 </View>
</View>
</Modal>
```

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

export default class App extends Component {

  items = ['one','two','three','four','five','six','seven','eight','nine','ten'];

  constructor(props) {
    super(props);
    StatusBar.setBarStyle('light-content', true);
    // StatusBar.setBackgroundColor('#008080', true); // Androidのみ
    this.title = 'Modal Layout';
    this.state = {
      message: 'This is ModalLayout.',
      modal: false
    }
  }

  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'
          }}
        />
        <View style={ styles.body }>
          <Text style={ styles.title }>{ this.title }</Text>
          <Text style={ styles.message }>{ this.state.message }</Text>

          <Modal
            animationType="fade"
            transparent={ true }
            visible={ this.state.modal }
            onRequestClose={ this.closeModal }
          >
          <View style={ styles.modalbase }>
            <View style={ styles.modalPanel }>
              <Text style={ styles.modalTitle }>Modal View</Text>
              <Text style={ styles.modalContent }>モーダル表示です</Text>
              <Button title="Close" onPress={ this.doModalAction } />
            </View>
          </View>
          </Modal>

          <View style={{ padding: 10 }}>
            <Button title="Click" onPress={ this.doAction } />
          </View>
        </View>

      </View>
    );
  }

  doAction = () => {
    this.setState({ modal: true });
  }
  doModalAction = () => {
    this.setState({
      modal: false,
      message: 'モーダルを閉じました'
    });
  }
  closeModal = () => {
    alert('Close Modal');
    this.setState({ modal: false });
  }

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

const styles = StyleSheet.create ({
  base: {
    padding: 0, 
    flex:1
  },
  body: {
    padding: 10, 
    flex:1
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold'
  },
  title: {
    textAlign: 'center',
    paddingTop: 20,
    paddingBottom: 10,
    fontSize: 25,
  },
  message: {
    textAlign: 'center',
    paddingBottom: 10,
    fontSize: 15,
  },
  modalbase: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#00000099'
  },
  modalPanel: {
    padding: 10,
    margin: 50,
    backgroundColor: 'rgba(255,255,255,0.8)',
    borderRadius: 10,
  },
  modalTitle: {
    textAlign: 'center',
    paddingTop: 20,
    paddingBottom: 10,
    fontSize: 25,
  },
  modalContent: {
    textAlign: 'center',
    paddingBottom: 10,
    fontSize: 15,
  }
});
```