[RN] React Native 使用 FlatList 实现九宫格布局

React Native 使用 FlatList 实现九宫格布局

先看图片演示实例:

本文以图片列表为例,实现九宫格布局!

主要有两种方法:

1)方法一:

利用FlatList的

numColumns ={2} // 一行2个

2)方法二:

利用 FlatList的

contentContainerStyle={styles.listViewStyle}

其中样式如下:

listViewStyle: {    // 主轴方向    flexDirection: ‘row‘,    // 一行显示不下,换一行    flexWrap: ‘wrap‘,    // 侧轴方向    alignItems: ‘center‘, // 必须设置,否则换行不起作用},

当然,有一个重要的前提是,列表中的元素宽度 当然也要设置为宽度的 1/N,

看实际使用例子代码:

import React, {Component} from ‘react‘;
import {FlatList, ActivityIndicator, Image, RefreshControl, Text, TouchableHighlight, View} from ‘react-native‘;
import Dimensions from ‘Dimensions‘;

import styles from ‘../../style/ImageStyle‘;
import ArrUtil from ‘../../util/ArrUtil‘;
import HttpRequest from ‘../../common/HttpRequest‘;

const baseUrl = ‘https://raw.githubusercontent.com/wukong1688/RN-AppNews/master/apk/data/image_list_‘;

const screenWidth = Dimensions.get(‘window‘).width;

let pageNo = 0;//当前第几页
let totalPage = 2;//总的页数

/**
 * 新闻主页
 */
class ImagePage extends Component {
    constructor(props) {
        super(props);
        //在这里定义json返回的key
        this.state = {
            //下拉刷新,上拉加载
            isRefreshing: true, //下拉刷新标记
            isLoading: false,  //上拉加载标记

            //data数据
            resultJson: null,
            error_code: ‘‘,
            reason: ‘‘,
            data: {},

            //网络请求状态
            error: false,
            errorInfo: "",

            showFoot: 0, // 控制foot, 0:隐藏footer  1:已加载完成,没有更多数据   2 :显示加载中
        }
    }

    componentDidMount() {
        pageNo = 0; //切换tab时 pageNo 也要归零
        this.fetchData(baseUrl + ‘0.json‘, 0); //默认从0页数据开始读
    }

    fetchData(url, pageNo) {
        const opts = {
            method: ‘GET‘,
            headers: HttpRequest.getHeaders(),
        };
        fetch(url, opts)
            .then((res) => {
                return res.json();
            })
            .then((response) => {
                this.setData(response);
            })
            .catch((error) => {
                alert(error);
                // console.error(error);
            })
            .done();
    }

    setData(response){
        let foot = 0;
        if (pageNo >= totalPage) {
            foot = 1;//listView底部显示没有更多数据了
        }

        let dataRes = [];
        let responseData = ArrUtil.shuffle(response.results);
        if (this.state.isRefreshing) {  //刷新,以前的数据全部清掉
            dataRes = responseData;
        } else {  //加载,数据追加到后面
            dataRes = this.state.data.concat(responseData);
        }

        this.setState({
            isRefreshing: false,
            isLoading: false,

            showFoot: foot,

            data: dataRes,
        });
    }

    //下拉刷新
    _onRefresh(type) {
        this.setState({
            showFoot: 2,
            isRefreshing: true
        });
        pageNo = 0; //刷新时,页码归0
        this.fetchData(baseUrl + type + ‘.json‘, type);
    }

    //列表点击事件
    itemClick(item, index) {
        this.props.navigation.navigate(‘ImageDetail‘, {
            title: item.desc,
            url: item.url,
        })
    }

    //FlatList的key
    _keyExtractor = (item, index) => index.toString();

    //子item渲染
    _renderItem = ({item, index}) => {
        let w = screenWidth * 0.5 - 7;
        let h = screenWidth * 0.65 - 7;
        let style = styles.itemPadding;

        return (

            <TouchableHighlight
                key={item._id}
                style={style}
                underlayColor={‘rgba(255,255,255,0.5)‘}
                onPress={this.itemClick.bind(this, item, index)}
            >
                <Image
                    defaultSource={require(‘../../res/image_icon.png‘)}
                    source={{uri: item.url}} style={{height: h, width: w}}
                    resizeMethod="resize"
                />
            </TouchableHighlight>

        )
    };

    //列表分割线
    _itemDivide = () => {
        return (
            <View style={{height: 1}}/>
        )
    };

    _renderFooter() {
        if (this.state.showFoot === 1) {
            return HttpRequest.renderMoreDataEmptyView();
        } else if (this.state.showFoot === 2) {
            return HttpRequest.renderMoreDataLoadingView();
        } else if (this.state.showFoot === 0) {
            return HttpRequest.renderMoreDataNoneView();
        }
    }

    _onEndReached() {
        //如果是正在加载中或没有更多数据了,则返回
        if (this.state.showFoot != 0) {
            return;
        }

        //如果当前页大于或等于总页数,那就是到最后一页了,返回
        if ((pageNo != 1) && (pageNo >= totalPage)) {
            return;
        } else {
            pageNo++;
        }
        //底部显示正在加载更多数据
        this.setState({
            showFoot: 2,
            isLoading: true,
        });
        //获取数据
        this.fetchData(baseUrl + pageNo + ‘.json‘, pageNo);
    }

    render() {
        //第一次加载等待的view
        if (this.state.isRefreshing && !this.state.error) {
            return HttpRequest.renderLoadingView();
        } else if (this.state.error) {
            //请求失败view
            return HttpRequest.renderErrorView(this.state.error);
        }
        //加载数据
        return this.renderData();
    }

    renderData() {
        return (

            <FlatList
                data={this.state.data}
                keyExtractor={this._keyExtractor}
                renderItem={this._renderItem}
                ItemSeparatorComponent={this._itemDivide}

                // 方法1)
                // numColumns ={2} // 一行2个

                // 方法2)
                contentContainerStyle={styles.listViewStyle}

                //下拉刷新
                refreshControl={
                    <RefreshControl
                        refreshing={this.state.isRefreshing}
                        onRefresh={this._onRefresh.bind(this, 0)}
                    />
                }

                //上拉加载
                ListFooterComponent={this._renderFooter.bind(this)}
                onEndReached={this._onEndReached.bind(this)}
                onEndReachedThreshold={1}
            />

        );
    }

}

module.exports = ImagePage;

样式:

listViewStyle: {
        // 主轴方向
        flexDirection: ‘row‘,
        // 一行显示不下,换一行
        flexWrap: ‘wrap‘,
        // 侧轴方向
        alignItems: ‘center‘, // 必须设置,否则换行不起作用
    },

参考:

https://blog.csdn.net/a_zhon/article/details/78137936

本博客地址: wukong1688

本文原文地址:https://www.cnblogs.com/wukong1688/p/10851764.html

转载请著名出处!谢谢~~

原文地址:https://www.cnblogs.com/wukong1688/p/10851764.html

时间: 2024-08-29 12:44:48

[RN] React Native 使用 FlatList 实现九宫格布局的相关文章

[RN] React Native 使用 react-native-camera 过程中报错 Found react-native-camera &#39;mlkit&#39; but wasn&#39;t required.`

详细报错如下: Could not resolve all task dependencies for configuration ':app:debugRuntimeClasspath'. Could not resolve project :react-native-camera. Required by: project :app > Cannot choose between the following configurations of project :react-native-ca

[RN] React Native FlatList跳转到顶部/底部

React Native FlatList跳转到顶部/底部 核心代码如下: <ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={styles.container} //下拉刷新 ,有 ScrollView 需要加载ScrollView,无则加到 FlatList refreshControl={ <RefreshControl refreshing={this.state.isRefreshing} o

React Native(一) FlexBox布局

欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/53241550 本文出自:[余志强的博客] 在React Native中主要使用FlexBox来布局. 安装过React Native的开发环境的就知道,在index.android.js/index.ios.js的文件内容如下: export default class TemplateDemo extends Component { render() { retu

React Native超棒的LayoutAnimation(布局动画)

该文翻译自:https://medium.com/@Jpoliachik/react-native-s-layoutanimation-is-awesome-4a4d317afd3e#.6syi2v6yh 刚创建的React Native技术交流群(282693535),欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送! 如果你是用React Native进行开发,然而还没有尝试过使用LayoutAnimation的话,

React Native之登录界面的布局

版权声明:本文为博主原创文章,未经博主允许不得转载. 代码注释比较详细 /** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React, {Component} from 'react'; import { AppRegistry, StyleSheet, Text, View, TextInput, Platform, TouchableOpacity, } fro

[RN] React Native 打包时 减少 Apk 的大小

React Native 打包时 减少 Apk 的大小 主要有两个方法: 在打包前设置 android\app\build.gradle 文件中 1) def enableProguardInReleaseBuilds = true 经测试,大概能减少 1M 之内的大小 2) def enableSeparateBuildPerCPUArchitecture = true 这个测试后就牛了,打包后的文件为大概 7~8M左右 不过需要注意的是,这里会分成多个平台 命名来分别拆分输出 就是了! 但挺

[RN] React Native 使用开源库 react-native-image-crop-picker 实现图片选择、图片剪裁

React Native 使用开源库 react-native-image-crop-picker 实现图片选择.图片剪裁 该库可以实现启动本地相册和照相机来采集图片,并且提供多选.图片裁剪等功能,支持iOS和Android两个平台,不同平台需要分别配置,详细的文字说明见github. 一.安装 npm install react-native-image-crop-picker -S react-native link react-native-image-crop-picker 二.配置 1

React Native——组件FlatList

属性 添加头部组件 ListHeaderComponent属性用来给FlatList添加头部组件 简单使用: //ES6之前写法 _header = function () { return ( <Text style={{fontWeight: 'bold', fontSize: 20}}>热门电影</Text> ); } <FlatList ListHeaderComponent={this._header}//header头部组件 /> 添加尾部组件 ListFo

React Native 之 Flexbox(弹性盒子布局)

Flexbox可以在不同屏幕上提供一致的布局结构,一般使用flexDirection.justifyContent.alignItems三个样式来辅助设计. 1.flexDirection:在组件的style中设置可以决定其子组件的主布局(主轴),默认是竖直方向 - 纵轴‘colunm’(从上到下依次排列子组件),另一个是横向 - 横轴‘row’(从左到右依次排列子组件).   2.justifyContent:决定子组件按照主轴的排列方式 A.flex-start:  从起始 -> 结尾方向开