ここ数週間、iOSでreact nativeを使用した後、フレックススタイリングのいくつかの欠点に遭遇したようです...特に「レスポンシブ」動作に関しては。
たとえば、カードを含むビューを作成するとします(これらのカードのメタデータはAPIから取得されます)。カードは、ビュー幅の50%からマージンとパディングを差し引いたものにし、2ごとに折り返す必要があります。
このビューの現在の実装では、返された配列が2つの項目を持つ行に分割されます。リストコンテナにはflex: 1, flexDirection: 'column
、行にはflex: 1
そして各カードにはflex: 1
。最終結果は、各行に2つの列があり、ビュー幅の半分を均等に占めることです。
Reactネイティブスタイルでこれを行う簡単な方法はないようです。JavaScriptを使用してデータに対して何らかの前処理を行い、正しくスタイルが設定されている必要があります。助言がありますか?
React Nativeはすでに パーセンテージサポートあり :
<View style={[style.parent]}>
<View style={[style.child, {backgroundColor: '#996666'} ]} />
<View style={[style.child, {backgroundColor: '#339966'} ]} />
<View style={[style.child, {backgroundColor: '#996633'} ]} />
<View style={[style.child, {backgroundColor: '#669933'} ]} />
</View>
var style = StyleSheet.create({
parent: {
width: '100%',
flexDirection: 'row',
flexWrap: 'wrap'
},
child: {
width: '48%',
margin: '1%',
aspectRatio: 1,
}
})
フレックスボックスでこれを実現するためのより良い方法があるかもしれませんが、私は通常、CSSビューポートサイズの測定単位にちなんで名付けられた、ビューポート幅とビューポート高さの「パーセンテージ」ヘルパーvw
とvh
を定義します。
import {Dimensions} from 'react-native';
function vw(percentageWidth) {
return Dimensions.get('window').width * (percentageWidth / 100);
}
function vh(percentageHeight) {
return Dimensions.get('window').height * (percentageHeight / 100);
}
グリッド内のアイテムをフローするには、マージンとビューポートサイズを考慮して、アイテムの適切なサイズを計算できます。
const COLUMNS = 3;
const MARGIN = vw(1);
const SPACING = (COLUMNS + 1) / COLUMNS * MARGIN;
const grid = {
flex: 1,
flexWrap: 'wrap',
flexDirection: 'row',
justifyContent: 'flex-start'
};
const cell = {
marginLeft: MARGIN,
marginTop: MARGIN,
width: vw(100) / COLUMNS - SPACING
}
return (
<View style={grid}>
{this.props.things.map(thing => <View style={cell} />)}
</View>
)
この手法は、アイテムの数がわかっていて限られている場合にのみ使用してください。カードの数が任意の場合、パフォーマンス上の理由からListView
を使用し、データセットを手動で行に分割する必要があります。
JustifyContentを使用できます: 'space-between'
<View style={styles.feed}>
<View style={styles.card} />
<View style={styles.card} />
<View style={styles.card} />
<View style={styles.card} />
</View>
feed: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
padding: 16,
justifyContent: 'space-between' }
card: {
backgroundColor: 'white',
width: '48%',
aspectRatio: 1,
marginBottom: 16 }