UNPKG

react-native-gridview

Version:

A flexible grid view based on React Native's ListView component.

280 lines (253 loc) 7.11 kB
import React, { Component } from 'react'; import { Platform, Slider, StyleSheet, Switch, Text, TouchableOpacity, View, } from 'react-native'; import GridView from 'react-native-gridview'; const BASE_SIZE = 30; const RANDOM_FACTOR_MAX = 30; class App extends Component { constructor(props) { super(props); this._itemCountChanged = this._itemCountChanged.bind(this); this._itemsPerRowChanged = this._itemsPerRowChanged.bind(this); this._randomizeContent = this._randomizeContent.bind(this); this._useRandomCountsChanged = this._useRandomCountsChanged.bind(this); this._renderTimeout = null; const itemCount = 10; const data = generateData(itemCount); this.state = { data, dataSource: null, itemCount, itemsPerRow: 4, variableContent: false, useRandomCounts: false, }; } render() { return ( <View style={styles.container}> {this._renderGridView()} {this._renderOptions()} </View> ); } _renderGridView() { return ( <GridView data={this.state.data} /** `dataSource` will override `data` */ dataSource={this.state.dataSource} padding={4} itemsPerRow={this.state.itemsPerRow} /** You can set different item counts for portrait and/or landscape mode */ // itemsPerRowPortrait={4} // itemsPerRowLandscape={7} renderItem={(item, sectionID, rowID, itemIndex, itemID) => { const randomValue = this.state.variableContent ? item.randomValue : BASE_SIZE; return ( <View key={item.key} style={[ styles.item, styles.itemSpacing, { backgroundColor: item.backgroundColor }, ]} > <Text style={{ fontSize: randomValue }}> {item.text} </Text> </View> ); }} renderSectionHeader={ this.state.useRandomCounts ? this._renderSectionHeader : null } /> ); } _renderOptions() { return ( <View style={styles.options}> <Text>Items per section</Text> <View style={styles.row}> <Slider style={styles.slider} minimumValue={1} maximumValue={10} step={1} value={this.state.itemsPerRow} onValueChange={this._itemsPerRowChanged} /> <Text style={styles.sliderText}>{this.state.itemsPerRow}</Text> </View> <Text>Item count</Text> <View style={styles.row}> <Slider style={styles.slider} minimumValue={10} maximumValue={250} step={1} value={this.state.itemCount} onValueChange={this._itemCountChanged} /> <Text style={styles.sliderText}>{this.state.itemCount}</Text> </View> <View style={[styles.row, { justifyContent: 'space-between' }]}> <TouchableOpacity style={styles.button} onPress={this._randomizeContent}> <Text style={styles.buttonText}>Randomize Content</Text> </TouchableOpacity> <View style={styles.row}> <Switch value={this.state.useRandomCounts} onValueChange={this._useRandomCountsChanged} /> <Text style={{ marginLeft: 8 }}>Vary items per row</Text> </View> </View> </View> ); } _renderSectionHeader(sectionData, sectionID) { return ( <View style={styles.row}> <Text>{sectionID}</Text> </View> ); } /** * Helper methods */ _createRandomRows(data) { const { itemsPerRow } = this.state; const rowData = []; for (let i = 0; i < data.length; i) { const endIndex = Math.max(Math.round(Math.random() * itemsPerRow), 1) + i; rowData.push(data.slice(i, endIndex)); i = endIndex; } return rowData; } _createRandomData(data) { return { 'Section 1': this._createRandomRows(data), 'Section 2': this._createRandomRows(data), 'Section 3': this._createRandomRows(data), }; } _createRandomDataSource(data) { const rowData = this._createRandomData(data); return new GridView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2, sectionHeaderHasChanged: (s1, s2) => s1 !== s2, }).cloneWithRowsAndSections(rowData); } _itemCountChanged(itemCount) { clearTimeout(this._renderTimeout); this._renderTimeout = setTimeout(() => { const data = generateData(itemCount); let dataSource = null; if (this.state.useRandomCounts) dataSource = this._createRandomDataSource(data); this.setState({ data, dataSource, itemCount, variableContent: false, }); }, 500); } _itemsPerRowChanged(itemsPerRow) { clearTimeout(this._renderTimeout); this._renderTimeout = setTimeout(() => { this.setState({ itemsPerRow }, () => this.forceUpdate()); if (this.state.useRandomCounts) { const randomData = this._createRandomData(this.state.data); this.setState({ dataSource: this.state.dataSource.cloneWithRowsAndSections(randomData), }); } }, 500); } _randomizeContent() { const data = generateData(this.state.itemCount); let dataSource = null; if (this.state.useRandomCounts) dataSource = this._createRandomDataSource(data); this.setState({ data, dataSource, variableContent: true, }); } _useRandomCountsChanged(useRandomCounts) { let { dataSource } = this.state; if (useRandomCounts) dataSource = this._createRandomDataSource(this.state.data); else dataSource = null; this.setState({ dataSource, useRandomCounts, }); } } function generateData(itemCount) { return Array(itemCount) .fill(null) .map((item, index) => { const colorIndex = index % 3; return { key: index, text: `${index + 1}`, randomValue: Math.random() * RANDOM_FACTOR_MAX + BASE_SIZE, backgroundColor: `#${colorIndex === 0 ? 'FF' : '88'}` + `${colorIndex === 1 ? 'FF' : '88'}` + `${colorIndex === 2 ? 'FF' : '88'}`, }; }); } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: Platform.OS === 'ios' ? 20 : 0, }, options: { padding: 10, borderTopWidth: StyleSheet.hairlineWidth, }, row: { flexDirection: 'row', alignItems: 'center', marginBottom: 4, }, slider: { flex: 1, }, sliderText: { width: 30, textAlign: 'right', }, button: { padding: 10, }, buttonText: { fontSize: 16, fontWeight: '600', color: '#007AFF', }, item: { flex: 1, borderColor: 'blue', borderWidth: StyleSheet.hairlineWidth, borderRadius: 6, justifyContent: 'center', alignItems: 'center', margin: 4, overflow: 'hidden', }, }); export default App;