React NativeのFlexboxで分かりにくい挙動を整理してみた
React Nativeのデザインの基本は<View>
コンポーネントを使用したflexboxデザインである。公式のドキュメントはこちら=>Layout with Flexbox
htmlにおけるdiv要素にdisplay:flex
, flex-direction: 'column'
を指定した挙動と似ているが、何故か<View>
で下位のDOMを囲うとUIが表示されなくなるなど意図しない挙動を示すことがあったので整理してみた。
flexDirectionのdefaultはcolumn
Htmlに馴染みがある人がまず戸惑うポイントである。flex-directionはwebサイトの場合はdefaultが横配置のrowであるが、React Nativeでは縦配置のcolumnとなっている。
Viewの幅は指定しない限り100%
上の写真で分かると思うが、緑背景が横100%で表示されている。flexDirectionをRowとしてもこれは変わらない。
幅を変更するためにはViewの横幅を数値で指定する必要がある。
またwidth:'80%'
とパーセントで記述することも可能である。
flex:1は親要素で確保されている領域全体を確保する
flexの指定を行うと、親要素の領域が確保され、RootのViewの場合は(それ以上親がいない場合は)画面全体の領域が確保される。どういうことか?まずはRootのViewに対してflex:1を指定してみる。すると、画面全体が緑色で覆われた。
紛らわしいのはこれからである。RootのViewをViewで囲ってみる。
画面全体ではなく、子要素が確保した領域のみが表示されている事が分かる。Rootの要素が領域を確保していないため、描画領域は実際に数値指定した領域に限られてしまうのである。なお、横については前述したとおり100%である。
親領域としての高さは0であるため、高さを指定しない場合やパーセントで指定した場合は画面に何も指定されなくなってしまう。
よって個別に領域を確保しないケースは、RootのViewからflex:1を指定することで領域を子要素に引き継ぐことがポイントとなる。
justifyContentとalignItems
justifyContentとalignItemsはReact Nativeのレイアウトでは頻繁に使用するが忘れがちであるためここでもまとめておく。
justifyContentは主軸(main axis)に対してレイアウトを整列するものである。主軸とはflexDirectionで指定されている、コンテンツを配置する方向のことである。すなわちflexDirectionがrowの時は横軸に対する整列で、columnの時は縦軸に対する整列となる。
一方で、alignItemsは交差軸に対してレイアウトを整列するものである。flexDirectionを変更すると、主軸と交差軸が入れ替わるので常に主軸がどちらにあるかを意識する必要がある。
下の例は、主軸が横軸で、横軸方向はcenter寄せを行い、副軸である縦軸方向はflex-end
を使用した終端合わせをしている。
描画領域と主軸を意識し、記述していくことが意図通り動作させるポイントとなる。
まとめ
ReactNativeのレイアウトで覚えておくべき点を最後にまとめておく。
- flexDirectionのdefaultはcolumn
- 横幅はflex指定あり、なしに関わらず100%
- flex:1で全体領域を確保
- 親領域が確保されていない場合は子要素が確保した領域に従う
この辺りに注意しておくと描画領域の状態が明確となり、その後alignItemsやjustifyContentをした時も意図通りの挙動となってくれるであろう。
また、動作確認のためには本記事のスクリーンショットでも使用しているように、公式ドキュメントに埋め込まれているExpoのサンドボックス環境を使用すると良い。手軽に試行錯誤ができるはずである。
Viewの描画領域を可視化するため、本サイトのようにViewのbackgroundColorを変更しておくと作業が捗るだろう。