針對FlatList組件,有2種九宮格實現方案:
(1)FlatList組件自帶的屬性,numColumns={4},分割爲4格子
(2)FlatList組件自帶的屬性,contentContainerStyle,修改其renderItem項樣式
contentContainerStyle={
flexDirection: 'row', // 必須
flexWrap: 'wrap', // 必須
justifyContent: 'flex-start',
}
針對SectionList組件的實現九宮格樣式,效果圖:
效果圖.png
數據結構如下:
{
"list": [
{
"title" : "美女集合",
"data": [
{
text: '水電費水電費',
source: require('../../assets/1.png'),
comment: '唧唧復唧唧',
},
{
text: '幸福感申達股份',
source: require('../../assets/2.png'),
comment: '神鼎飛丹砂',
},
...
]
},
]
}
修改後的結構(只是多加了一層數組殼data:[[{...}]]):
{
"list": [
{
"title" : "美女集合",
"data": [
[
{
text: '水電費水電費',
source: require('../../assets/1.png'),
comment: '唧唧復唧唧',
},
{
text: '幸福感申達股份',
source: require('../../assets/2.png'),
comment: '神鼎飛丹砂',
},
...
]
]
},
]
}
分組列表代碼如下:
const { data } = this.state;
const sections = [];
if (sections.length === 0) {
sections.push({
key: 'today',
data: [this.state.data],
});
sections.push({
key: 'yesterday',
data: [this.state.data],
});
sections.push({
key: 'earlier',
data: [this.state.data],
});
}
<SectionList
renderSectionHeader={this.sectionHearer}
renderItem={this._renderItem}
sections={sections}
refreshControl={
<RefreshControl
// size={RefreshControl.SIZE.LARGE} // size屬性改變Android上的indicator的大小,值默認爲DEFAULT,可以改成 LARGE.
enabled
colors={[OAColor.headBg, 'white']} // colors屬性改變Android上的indicator的顏色,值爲數組,可以只設置一個顏色,
tintColor={OAColor.headBg} // tintColor屬性改變iOS上的indicator的顏色,只能指定一個值。
refreshing={false}
onRefresh={this._onRefresh}
/>
}
// ItemSeparatorComponent={() => (
// <WhiteSpace />
// )}
onEndReached={this._onEndReached}
onEndReachedThreshold={0.01}
ListHeaderComponent={() => <WhiteSpace />}
ListFooterComponent={this.renderFooterView}
/>
完整代碼:(1)MaterialLibraryContainer.js
/**
* @flow
* @author [email protected]
* @description 上傳圖片
*/
import React, { Component } from 'react';
import {
Dimensions,
SafeAreaView,
Text,
View,
StyleSheet,
TouchableOpacity,
Image,
SectionList,
RefreshControl,
ScrollView,
} from 'react-native';
import MasonryList from './components/MasonryList';
import PlaceholderImage from './components/PlaceholderImage';
import OAColor from '../../theme/OAColor';
import { SectionItem } from '../../components';
import { WhiteSpace } from 'antd-mobile';
import OASize from '../../constants/OASize';
const { width, height } = Dimensions.get('window');
export default class MaterialLibraryContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
refreshing: false,
data: [
{
text: '水電費水電費',
source: require('../../assets/1.png'),
comment: '唧唧復唧唧',
},
{
text: '幸福感申達股份',
source: require('../../assets/2.png'),
comment: '神鼎飛丹砂',
},
{
text: '水電費水電費',
source: require('../../assets/3.png'),
comment: '唧唧復唧唧',
},
{
text: '幸福感申達股份',
source: require('../../assets/4.png'),
comment: '神鼎飛丹砂',
},
{
text: '水電費水電費',
source: require('../../assets/5.png'),
comment: '唧唧復唧唧',
},
{
text: '幸福感申達股份',
source: require('../../assets/6.png'),
comment: '神鼎飛丹砂',
},
{
text: '水電費水電費',
source: require('../../assets/7.png'),
comment: '唧唧復唧唧',
},
{
text: '幸福感申達股份',
source: require('../../assets/8.png'),
comment: '神鼎飛丹砂',
},
{
text: '水電費水電費',
source: require('../../assets/9.png'),
comment: '唧唧復唧唧',
},
{
text: '幸福感申達股份',
source: require('../../assets/10.png'),
comment: '神鼎飛丹砂',
},
],
np: 0,
};
}
componentDidMount = () => {
this.onRefreshing();
};
onRefreshing = () => {
console.log('onRefreshing-------');
};
_onEndReached = () => {
console.log('_onEndReached-------');
};
_keyExtractor = (item, index) => {
return item.text + index;
};
_renderItem = ({ item }) => {
// console.warn('item:::', item);
return (
<View
style={{
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'flex-start',
}}
>
{item &&
item.length > 0 &&
item.map((it, i) => {
return (
<TouchableOpacity
key={i}
activeOpacity={0.7}
// onPress={() => this._onPressContent(item)}
style={[
styles.item,
{ paddingLeft: i % 4 === 0 ? OASize(1) : 0 },
]}
>
<Image
source={it.source}
resizeMode="cover"
placeholder={{ uri: 'placeholder' }}
style={{
width: (width - 10) / 4,
height: (width - 10) / 4,
// borderRadius: 4,
}}
/>
</TouchableOpacity>
);
})}
</View>
);
};
_onPressContent = (item) => {
//
};
sectionHearer = ({ section }) => {
let title = '';
switch (section.key) {
case 'today':
title = '今天';
break;
case 'yesterday':
title = '昨天';
break;
default:
title = '更早';
break;
}
return (
<SectionItem
title={title}
style={{ backgroundColor: '#2d3031', paddingHorizontal: OASize(5), height: OASize(30), }}
leftIconStyle={{ width: 0 }}
titleStyle={{ color: OAColor.white }}
/>
);
};
render() {
const { data } = this.state;
const sections = [];
if (sections.length === 0) {
sections.push({
key: 'today',
data: [this.state.data],
});
sections.push({
key: 'yesterday',
data: [this.state.data],
});
sections.push({
key: 'earlier',
data: [this.state.data],
});
}
return (
<SafeAreaView style={styles.container}>
<SectionList
renderSectionHeader={this.sectionHearer}
renderItem={this._renderItem}
sections={sections}
refreshControl={
<RefreshControl
// size={RefreshControl.SIZE.LARGE} // size屬性改變Android上的indicator的大小,值默認爲DEFAULT,可以改成 LARGE.
enabled
colors={[OAColor.headBg, 'white']} // colors屬性改變Android上的indicator的顏色,值爲數組,可以只設置一個顏色,
tintColor={OAColor.headBg} // tintColor屬性改變iOS上的indicator的顏色,只能指定一個值。
refreshing={false}
onRefresh={this._onRefresh}
/>
}
// ItemSeparatorComponent={() => (
// <WhiteSpace />
// )}
onEndReached={this._onEndReached}
onEndReachedThreshold={0.01}
ListHeaderComponent={() => <WhiteSpace />}
ListFooterComponent={this.renderFooterView}
/>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#2d3031',
},
item: {
margin: 1,
},
itemText: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 10,
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: 30,
backgroundColor: '#0002',
// borderBottomLeftRadius: 4,
// borderBottomRightRadius: 4,
},
});
完整代碼:(2)SectionItem.js
/**
* @flow
* @author [email protected]
* @description arrow item
*/
import React, { PureComponent } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import IconView from '../widget/IconView';
import OAColor from '../theme/OAColor';
import OASize from '../constants/OASize';
import OAVariables from '../constants/OAVariables';
import OAStyles from '../theme/OAStyles';
type Props = {
onPress: Function,
style: any, //combine style
pressColor?: string,
textColor?: string,
title: string,
rightBtnText?: string,
titleStyle?: object,
leftIconStyle?: object,
onRightBtnPress?: Function,
};
export class SectionItem extends PureComponent<Props> {
props: Props;
render() {
const {
onPress,
style,
pressColor,
titleStyle,
leftIconStyle,
title,
rightBtnText,
onRightBtnPress,
} = this.props;
const targetColor = pressColor ? pressColor : 'white';
const tTxtColor = tTxtColor ? tTxtColor : OAColor.accent;
return (
<View
underlayColor={targetColor}
onPress={onPress}
>
<View style={[styles.item_container, style]}>
<View style={styles.item_wrap}>
<View style={[styles.splitBlock, leftIconStyle]} />
<TouchableOpacity onPress={onPress}>
<Text
style={[styles.txt, { color: OAColor.black }, titleStyle]}
numberOfLines={1}
ellipsizeMode="tail"
>
{title}
</Text>
</TouchableOpacity>
</View>
{!!rightBtnText && (
<TouchableOpacity onPress={onRightBtnPress}>
<View style={styles.item_wrap}>
<Text style={[styles.rightBtnTxt]}>{rightBtnText}</Text>
<IconView type={'\uf604'} size={15} color={OAColor.lightText} />
</View>
</TouchableOpacity>
)}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
item_container: {
borderBottomWidth: OASize(0.5),
backgroundColor: 'white',
paddingHorizontal: OAVariables.h_spacing_lg,
borderBottomColor: 'rgba(0, 0, 0, 0.1)',
height: OASize(42.5),
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
item_wrap: {
flexDirection: 'row',
alignItems: 'center',
},
txt: {
...OAStyles.font,
fontSize: OASize(18),
fontWeight: 'bold',
lineHeight: 30,
height: OASize(30),
marginRight: OASize(10),
},
rightBtnTxt: {
...OAStyles.font,
fontSize: OASize(14),
lineHeight: 30,
color: OAColor.descText,
marginRight: OASize(5),
},
splitBlock: {
width: OASize(3),
height: OASize(15),
backgroundColor: OAColor.headBg,
marginRight: OASize(6),
},
});