最近Expoでアプリ書いてるのに使ったTipsなど

React Native Advent Calendar 2018 - 17日目の記事です

最近Expoでアプリを書いているので、そこで使った小ネタを紹介

画面全体を覆うスタイルを定義したい時

Stylesheet.absoluteFillObject

画面全体をピッタリ覆うスタイルを付けたい時に使えます

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity>
          <Text>Button</Text>
        </TouchableOpacity>
        <View style={styles.fill} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  fill: {
    // 縦横いっぱいでabsoluteなViewのスタイルを設定
    ...StyleSheet.absoluteFillObject,
    // わかりやすく色を付けてる
    backgroundColor: 'rgba(255, 0, 0, 0.2)'
  }
});

f:id:rskull:20181216205956p:plain

赤くなってる範囲が <View />absoluteFillObject を設定した範囲です

いつ使うのか? 例えば環境に影響されない(どこに置いても成り立つ)フローティングボタンを作りたい場合などに使えます

f:id:rskull:20181216210052p:plain

被さったViewのタッチ判定を無効化する

当たり前ですが、このままだと赤いマスクの裏の画面が全く触れなくなってしまいます

そんな時は <View />pointerEvents="box-none" を設定します

      <View style={styles.fill} pointerEvents="box-none">
        // ...
      </View>

全面にある赤い <View /> のタップ判定を無効にして、なにもないように振る舞わせることができます

f:id:rskull:20181216205853g:plain

意外と色んなところで使えそう

キーボードの上に「完了」とか付けるやつの実装

これ、よく使うと思います

f:id:rskull:20181216211520p:plain

RNにもともと入ってる InputAccessoryView コンポーネントで実装はできますが、バギーで使えませんでした

自分で実装したんですが、ここでも pointerEvents="box-none" が出てきます

スペーサーに外部のライブラリ使ってますが

import React from 'react';
import { View, ViewProps, StyleSheet } from 'react-native'
import KeyboardSpacer from 'react-native-keyboard-spacer';

interface Props extends ViewProps {
  children: React.ReactNode;
}

export const InputAccessoryView = ({ children, ...rest }: Props) => (
  <View {...rest} pointerEvents="box-none" style={styles.wrap}>
    {children}
    <KeyboardSpacer />
  </View>
)

const styles = StyleSheet.create({
  wrap: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: 'flex-end',
  }
})

children がキーボードの上に乗るところです

あとはこのコンポーネントを使って好きに実装します

import React from 'react';
import { View, ViewProps, TouchableOpacity, Text, Keyboard } from 'react-native'
import { InputAccessoryView} from './InputAccessoryView'
import styled from 'styled-components'

const Inner = styled(View)`
  align-items: flex-end;
  padding: 12px 16px;
  background: #f2f2f2;
`;

const TextButton = styled(TouchableOpacity)`
  font-weight: bold;
  color: #15a2ff;
`;

interface Props extends ViewProps {
  visible?: boolean;
  onClosed?: () => void
}

export const InputAccessory = ({ visible, onClosed, ...rest }: Props) => {
  if (visible === false) {
    return null
  }

  return (
    <InputAccessoryView {...rest}>
      <Inner>
        <TextButton
          onPress={() => {
            if (onClosed) {
              onClosed()
            }
            Keyboard.dismiss()
          }}
        >
          <Text>完了<Text>
        </TextButton>
      </Inner> 
    </InputAccessoryView>
  )
}

Accessory.defaultProps = {
  visible: true,
  onClosed: undefined,
}

例えばこんな感じ

「完了」ボタンを置いてキーボードが閉じるように実装します

<InputAccessoryView /> はただキーボードの上に乗る要素を作るだけのコンポーネントです

f:id:rskull:20181216212906g:plain

https://gist.github.com/rskull/3fb91f4c19f49d86355987d1c35fbb35

まとめ

かなりざっとな記事ですみません

3ヶ月くらいExpoで開発してる感想は、めっちゃ楽の一言でした

以前素のRNを2年半くらい触ってましたが、ビルドは落ちるし時間かかるしで辛かったです(当方ネイティブ初心者なので...)

プロジェクトごとにアカウントを作って、そのアカウントをメンバーで共有すれば

コマンドでデプロイ後すぐにシェア、確認できるのですごい作業がはかどりました

なんとかリリースまでこぎつけたいですね

以上です。良いお年を