You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
1.8 KiB
74 lines
1.8 KiB
2 months ago
|
import React from 'react';
|
||
|
import { View, ViewStyle, StyleSheet } from 'react-native';
|
||
|
import { getScreenWidth, isTablet } from '../utils/dimensions';
|
||
|
import { spacing } from '../constants/styles';
|
||
|
|
||
|
interface ResponsiveGridProps {
|
||
|
children: React.ReactNode;
|
||
|
style?: ViewStyle;
|
||
|
columns?: number;
|
||
|
gap?: 'none' | 'sm' | 'md' | 'lg';
|
||
|
padding?: 'none' | 'sm' | 'md' | 'lg';
|
||
|
}
|
||
|
|
||
|
export const ResponsiveGrid: React.FC<ResponsiveGridProps> = ({
|
||
|
children,
|
||
|
style,
|
||
|
columns = 2,
|
||
|
gap = 'md',
|
||
|
padding = 'md',
|
||
|
}) => {
|
||
|
const screenWidth = getScreenWidth();
|
||
|
const isTabletDevice = isTablet();
|
||
|
|
||
|
// 根据设备类型调整列数
|
||
|
const adjustedColumns = isTabletDevice ? Math.min(columns * 1.5, 4) : columns;
|
||
|
|
||
|
// 计算间距
|
||
|
const gapSize = gap === 'none'
|
||
|
? 0
|
||
|
: gap === 'sm'
|
||
|
? spacing.sm
|
||
|
: gap === 'lg'
|
||
|
? spacing.lg
|
||
|
: spacing.md;
|
||
|
|
||
|
// 计算内边距
|
||
|
const paddingSize = padding === 'none'
|
||
|
? 0
|
||
|
: padding === 'sm'
|
||
|
? spacing.sm
|
||
|
: padding === 'lg'
|
||
|
? spacing.lg
|
||
|
: spacing.md;
|
||
|
|
||
|
// 计算每个项目的宽度
|
||
|
const itemWidth = (screenWidth - (paddingSize * 2) - (gapSize * (adjustedColumns - 1))) / adjustedColumns;
|
||
|
|
||
|
// 将子元素转换为数组
|
||
|
const childrenArray = React.Children.toArray(children);
|
||
|
|
||
|
return (
|
||
|
<View style={[styles.container, { padding: paddingSize }, style]}>
|
||
|
<View style={[styles.grid, { gap: gapSize }]}>
|
||
|
{childrenArray.map((child, index) => (
|
||
|
<View key={index} style={{ width: itemWidth }}>
|
||
|
{child}
|
||
|
</View>
|
||
|
))}
|
||
|
</View>
|
||
|
</View>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
const styles = StyleSheet.create({
|
||
|
container: {
|
||
|
flex: 1,
|
||
|
width: '100%',
|
||
|
},
|
||
|
grid: {
|
||
|
flexDirection: 'row',
|
||
|
flexWrap: 'wrap',
|
||
|
justifyContent: 'flex-start',
|
||
|
},
|
||
|
});
|