關於react-native 的 SectionList組件、FlatList組件實現九宮格樣式(類似相冊多item項排列)

針對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),
  },
});

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章