プログラム関係の備忘録。技術系記事1000記事以上を目指すブログ

react-nativeでのそれっぽい最小限のUI構築

react-native-router-flux、native-baseを使ってアプリケーションの土台作り。

パッケージインストール

react-native-router-fluxのインストール

npm i -save react-native-router-flux

私の環境では上記だけではreact-native-router-fluxでの画面遷移が上手くいかず、以下のエラーが発生。

Unable to resolve module ‘react-native-screen’

こんな感じのエラーが出てしまい、以下のライブラリが必要だったので追加しました。

npm i --save react-native-gesture-handler react-native-reanimated react-native-screens

native-baseのインストール

npm i --save native-base

react-native-router-fluxを使った画面遷移のシンプルな例

各ページをwrapするコンポーネントを定義する

import React, {Component} from 'react';
import { Scene, Router } from 'react-native-router-flux';
import Home from './page/Home';
import MyPage from './page/MyPage';

export default class Wrapper extends Component {
  render() {
    return (
    <Router>
        <Scene>
            <Scene key="Home" 
                component={Home} 
                initial
            />
            <Scene key="MyPage" 
                component={MyPage} 
            />
        </Scene>
    </Router>
    );
  }
}

各ページを定義する

import React, {Component} from 'react';
import { Container, Header,Content, Left, Body, Right, Button, Icon, Title } from 'native-base';
import FooterArea from './Sections/FooterArea';

export default class Home extends Component {
  render() {
    return (
      <Container>
        <Header>
          <Left>
            <Button transparent}>
              <Icon name='menu' />
            </Button>
          </Left>
          <Body>
            <Title>Header</Title>
          </Body>
          <Right />
        </Header>
        <Content/>
        <FooterArea/>
      </Container>
    );
  }
}
import React, { Component } from 'react';
import {Container,Header,Title,Content, Button,Left,Right,Body,Icon} from 'native-base';
import { Actions } from 'react-native-router-flux';
import FooterArea from './Sections/FooterArea';

class MyPage extends Component {
  render() {
    return (
      <Container>
        <Header>
          <Left>
            <Button transparent>
              <Icon name='arrow-back'
                onPress={ () => Actions.Mypage() }
              />
            </Button>
          </Left>
          <Body>
            <Title>タイトル</Title>
          </Body>
          <Right>
            <Button transparent>
              <Icon name='menu' />
            </Button>
          </Right>
        </Header>
        <Content>
        </Content>
        <FooterArea/>
      </Container>
    )
  }
}
 

export default MyPage;
import React, { Component } from 'react';
import { Text } from 'react-native';
import {Footer, Button,Icon} from 'native-base';
import { Actions } from 'react-native-router-flux';

class FooterArea extends Component {
  render() {
    return (
        <Footer>
            <Button active
                onPress={ () =>Actions.Home()}
            >
              <Icon ios='ios-paper' android="md-paper" />
              <Text >Home</Text>
            </Button>
            <Button
              onPress={ () =>Actions.MyPage()}
            >
              <Icon ios='ios-bookmark' android="md-bookmark" />
              <Text >MyPage</Text>
            </Button>
        </Footer>
    )
  }
}
 

export default FooterArea;

実装の際にいくつか気づいたポイント

react-native特有というか、パッケージ特有の指定の仕方など。

react-native-router-fluxのヘッダーを使用しない

react-native-router-fluxを使うとデフォルトで”ヘッダーのナビゲーション”が付いてきますが、ヘッダーはnative-baseに任せたかったので非表示にしたかった。

sceneにhideNavBar={true}を追加します。

<Scene key="Home" 
  component={Home} 
  initial
  hideNavBar={true}
/>

これでOK

react-native-router-fluxで前の画面に戻る

Actions.pop()を使う。
いまの画面を更新するにはActions.refresh()

native-baseのheaderを透明にする

<Header
  transparent
>

transparentを追加するだけ

native-baseでのmarginやpaddingの指定など

bootstrap4に馴染みがあると「col-**」といった感じで手軽にできるのかなーと思っていましたが、特になさそう。

以下のように各コンポーネントにStyleSheetで定義するようにしました。

import { StyleSheet } from 'react-native';

class *** extends Component {
~~~
  <Container style={style.container}>
  </Container>
}
export default ***

const style = StyleSheet.create({
  container: {
    backgroundColor: '#eee'
  },
});

react-nativeで使えるフォントなど

デフォルトでも以下に載っているものは指定できるよう。
https://github.com/react-native-training/react-native-fonts

react-nativeで背景画像を設定する方法

大きく2通り

react-nativeのImageをImportし、スタイルで背景画像として割り当てる

import { Image} from 'react-native';
・
・
<Image
  source={require('../***.png')}
  style={{position: 'absolute', bottom: 0, zIndex: -1}}
/>

react-nativeのImageBackgroundを使用する

import { ImageBackground,StyleSheet } from 'react-native';
・
・
<ImageBackground source={require('../***.jpg')} style={style.image}>
</ImageBackground>

const style = StyleSheet.create({
  image: {
    flex: 1,
    resizeMode: "cover",
    justifyContent: "center",
    paddingBottom:20
  }
})

ButtonのイベントにはonPressを使う

webでreactを使うのに慣れているとついonClickでもいけちゃうと思いますが、onClickではなくonPressを使う