Flexboxでレイアウトする
Flexboxは、UIをある方向に並べるという、ブラウザの世界にありそうでなかった仕様を実現するために用意されたCSSプロパティ群です。YogaというレイアウトエンジンはFlexboxの解釈と再現を目的に作られたため、React NativeのスタイルでもFlexboxが多用されます。リスト4のように、横に並べた要素が自動で折り返す処理なども、比較的容易に記述できます。
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
export const Flexbox = () => (
<View style={styles.container}>
<Text style={styles.item}>Item 1</Text>
<Text style={styles.item}>Item 2</Text>
<Text style={styles.item}>Item 3</Text>
<Text style={styles.item}>Item 4</Text>
<Text style={styles.item}>Item 5</Text>
<Text style={styles.item}>Item 6</Text>
</View>
);
const styles = StyleSheet.create({
container: {
// display: 'flex' // デフォルトでflexなので指定しない
flexDirection: 'row', // (2) 横方向に並べる
flexWrap: 'wrap', // (3) 折り返す
},
item: {
// (1) 100x100の正方形を作る
width: 100,
height: 100,
// 見やすいように枠線をつける
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#bbb'
}
});
(1)で100 x 100の正方形に加工したTextコンポーネントを、(2)の指定で横方向に並べます。縦で持ったときのスマートフォンでは、正方形を横方向に6つも並べられないので、(3)の指定で折り返しを許可しています。リスト4のコンポーネントを表示すると、図6のようになります。
指定したとおり、親要素の中に子要素が入りきらないと判断した時点で、折り返す処理が行われています。多様な画面サイズに対応することが求められるスマートフォンアプリでは、とてもうれしい挙動です。
Flexboxのプロパティ
React Nativeでは、次のプロパティが用意されています。
- flexBasis:子要素の幅を指定する
- flexGrow:子要素をどの程度伸ばしてもよいかを指定する
- flexShrink:子要素をどの程度縮めてもよいかを指定する
-
flex:
flexShrink: 1, flexBasis: 0を前提としたflexGrowを指定する - flexDirection:子要素を並べる方向を指定する
- flexWrap:子要素を親要素の端で折り返すかどうかを指定する
-
justifyContent:子要素を
flexDirectionの方向でどちらに寄せるかを指定する -
alignContent:子要素を
flexDirectionの垂直方向でどちらに寄せるかを指定する -
alignSelf:子要素1つ分の中身を
flexDirectionの垂直方向でどちらに寄せるかを指定する -
alignItems:子要素すべての中身を
flexDirectionの垂直方向でどちらに寄せるかを指定する
React Nativeで使えるFlexbox仕様の多くは、ブラウザと共通です。ただし、スマートフォンアプリを開発することに主眼を置いた環境であることから、次のプロパティについてはデフォルトの設定がブラウザと異なります。
-
display: 'flex'が暗黙に指定されている -
flexDirection: 'column'が暗黙に指定されている(ブラウザはrowがデフォルト)
この2点があることで、「コンテンツを上から下に並べる」というレイアウトについては、スタイルを指定せずに実現できます。
absoluteやpositionでレイアウトする
React Nativeのレイアウトは、基本的にはFlexboxで組んでいくことになります。しかし、マテリアルデザインのFloating Action Buttonのように、画面の右下に重なって配置するボタンを、Flexboxだけで実現するのは困難です。こういった場合に便利なのが、CSSにおける位置の指定方法である、position: 'absolute'です(リスト4)。
import React from 'react';
import { View, StyleSheet, SafeAreaView } from 'react-native';
import { WidthHeight } from './WidthHeight';
import { MarginPadding } from './MarginPadding';
import { Flexbox } from './Flexbox';
export default function App() {
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<WidthHeight />
<MarginPadding />
<Flexbox />
<View style={styles.button} />{/* (1) */}
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
button: {
// 100x100の赤いビュー
width: 100,
height: 100,
backgroundColor: 'red',
// (2) 右下に配置する
position: 'absolute',
right: 16,
bottom: 16,
}
});
(1)のビューをFloating Action Buttonに見立てて、(2)の指定で画面の右下に表示します。実際に表示したのが以下です(図7)。
右下に赤い四角が表示されました。使いどころはあまり多くはありませんが、画面内で場所を固定したい表示がある場合は力を発揮するので、ぜひ覚えておきましょう。
まとめ
前回と今回の2回に分けて、React Nativeのスタイルについて解説しました。レイアウトエンジンであるYogaが、CSSのプロパティの多くを再現するおかげで、CSSの知識を用いてモバイルアプリのUIを組み上げることが可能です。細かい使い方を調べる場合には、世の中のブラウザ向けのブログ記事が助けになるでしょう。次回はUIライブラリを使って、手軽に美しいUIを作り出す方法を解説します。
