mirror of
https://github.com/zhigang1992/react-native-super-grid.git
synced 2026-01-12 22:50:58 +08:00
174 lines
3.8 KiB
JavaScript
174 lines
3.8 KiB
JavaScript
import React, { Component } from 'react';
|
|
import {
|
|
View, Dimensions, ViewPropTypes, SectionList,
|
|
} from 'react-native';
|
|
import PropTypes from 'prop-types';
|
|
import { generateStyles, calculateDimensions, chunkArray } from './utils';
|
|
|
|
class SectionGrid extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.onLayout = this.onLayout.bind(this);
|
|
this.renderRow = this.renderRow.bind(this);
|
|
|
|
const { staticDimension } = props;
|
|
|
|
// Calculate total dimensions and set to state
|
|
let totalDimension = staticDimension;
|
|
if (!staticDimension) {
|
|
totalDimension = Dimensions.get('window').width;
|
|
}
|
|
|
|
this.state = {
|
|
totalDimension,
|
|
};
|
|
}
|
|
|
|
onLayout(e) {
|
|
const { staticDimension, onLayout } = this.props;
|
|
const { totalDimension } = this.state;
|
|
|
|
if (!staticDimension) {
|
|
const { width: newTotalDimension } = e.nativeEvent.layout || {};
|
|
|
|
if (totalDimension !== newTotalDimension) {
|
|
this.setState({
|
|
totalDimension: newTotalDimension,
|
|
});
|
|
}
|
|
}
|
|
|
|
// call onLayout prop if passed
|
|
if (onLayout) {
|
|
onLayout(e);
|
|
}
|
|
}
|
|
|
|
renderRow({
|
|
rowItems,
|
|
rowIndex,
|
|
section,
|
|
itemsPerRow,
|
|
rowStyle,
|
|
separators,
|
|
isFirstRow,
|
|
containerStyle,
|
|
}) {
|
|
const { spacing, itemContainerStyle, renderItem } = this.props;
|
|
|
|
// Add spacing below section header
|
|
let additionalRowStyle = {};
|
|
if (isFirstRow) {
|
|
additionalRowStyle = {
|
|
marginTop: spacing,
|
|
};
|
|
}
|
|
|
|
return (
|
|
<View style={[rowStyle, additionalRowStyle]}>
|
|
{rowItems.map((item, i) => (
|
|
<View
|
|
key={`item_${(rowIndex * itemsPerRow) + i}`}
|
|
style={[containerStyle, itemContainerStyle]}
|
|
>
|
|
{renderItem({
|
|
item,
|
|
index: (rowIndex * itemsPerRow) + i,
|
|
section,
|
|
separators,
|
|
rowIndex,
|
|
})}
|
|
</View>
|
|
))}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
render() {
|
|
const {
|
|
sections,
|
|
style,
|
|
spacing,
|
|
fixed,
|
|
itemDimension,
|
|
staticDimension,
|
|
renderItem,
|
|
onLayout,
|
|
...restProps
|
|
} = this.props;
|
|
|
|
const { totalDimension } = this.state;
|
|
|
|
const { containerDimension, itemsPerRow, fixedSpacing } = calculateDimensions({
|
|
itemDimension,
|
|
staticDimension,
|
|
totalDimension,
|
|
spacing,
|
|
fixed,
|
|
});
|
|
|
|
const { containerStyle, rowStyle } = generateStyles({
|
|
itemDimension,
|
|
containerDimension,
|
|
spacing,
|
|
fixedSpacing,
|
|
fixed,
|
|
});
|
|
|
|
const groupedSections = sections.map((section) => {
|
|
const chunkedData = chunkArray(section.data, itemsPerRow);
|
|
|
|
return {
|
|
...section,
|
|
data: chunkedData,
|
|
originalData: section.data,
|
|
};
|
|
});
|
|
|
|
|
|
return (
|
|
<SectionList
|
|
sections={groupedSections}
|
|
renderItem={({ item, index, section }) => this.renderRow({
|
|
rowItems: item,
|
|
rowIndex: index,
|
|
section,
|
|
isFirstRow: index === 0,
|
|
itemsPerRow,
|
|
rowStyle,
|
|
containerStyle,
|
|
})}
|
|
keyExtractor={(_, index) => `row_${index}`}
|
|
style={style}
|
|
onLayout={this.onLayout}
|
|
ref={(sectionList) => { this.sectionList = sectionList; }}
|
|
{...restProps}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
|
|
SectionGrid.propTypes = {
|
|
renderItem: PropTypes.func.isRequired,
|
|
sections: PropTypes.arrayOf(PropTypes.any).isRequired,
|
|
itemDimension: PropTypes.number,
|
|
fixed: PropTypes.bool,
|
|
spacing: PropTypes.number,
|
|
style: ViewPropTypes.style,
|
|
itemContainerStyle: ViewPropTypes.style,
|
|
staticDimension: PropTypes.number,
|
|
onLayout: PropTypes.func,
|
|
};
|
|
|
|
SectionGrid.defaultProps = {
|
|
fixed: false,
|
|
itemDimension: 120,
|
|
spacing: 10,
|
|
style: {},
|
|
itemContainerStyle: undefined,
|
|
staticDimension: undefined,
|
|
onLayout: null,
|
|
};
|
|
|
|
export default SectionGrid;
|