自定義上下拉刷新----FlatList

效果圖:

首次加載.png
下拉刷新.png
上拉刷新.png

FlatListPage文件

頭文件包含

import {
    ActivityIndicator,
    Alert,
    Dimensions,
    FlatList,
    Image,
    RefreshControl,
    StyleSheet,
    Text,
    TouchableOpacity,
    View
} from 'react-native';
import {XLImageButton} from "../common/XLButton";
import {NavigationBarTitle} from "../common/NavigationBarTitle";
import {appStyle} from "../style/BaseStyles";

列表json數(shù)據(jù)

const list = [{
    title: '美仁棗300g',
    imageUrl: 'https://a.vpimg4.com/upload/merchandise/pdcvis/602520/2018/0611/93/7f380e8c-627e-4162-b68c-a16ad98f9609_5t.jpg',
    price: 38,
}, {
    title: '2件起售】香蕉干90g',
    imageUrl: 'https://a.vpimg2.com/upload/merchandise/pdcvis/610789/2018/0420/114/54c7ae6a-1b94-44d9-bd38-0d46326aa683_t.jpg',
    price: 19,
}, {
    title: '【2件起售】七彩葡萄干420g',
    imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/602520/2018/0611/81/faf4abe6-e212-4347-9369-118028bec2fe_5t.jpg',
    price: 27,
}, {
    title: '優(yōu)你康罐裝牛奶雙味棒棒糖720g',
    imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/605346/2018/0509/184/5a1c29d8-b127-40c5-b239-4b0c5b5b1e1b.jpg',
    price: 128,
}, {
    title: '滇園南棗核桃糕148g*2福建特產(chǎn)小吃休閑糖果零食軟糖喜糖',
    imageUrl: 'https://a.vpimg4.com/upload/merchandise/pdcvis/606282/2018/0424/132/5bf877ba-9a13-4f85-a67c-2ea2fbbe13f9_t.jpg',
    price: 59,
}, {
    title: '【2件起售】自然派榴蓮糖200g',
    imageUrl: 'https://a.vpimg2.com/upload/merchandise/pdcvis/605222/2018/0320/1/9edf6130-35f1-4af8-9034-bf37a617c82a.jpg',
    price: 22,
}, {
    title: '【樂(lè)奈】8口味速融巧克力408g',
    imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/131932/2018/0530/137/083642ef-5fef-446c-b279-7a3047ba058e_5t.jpg',
    price: 39,
}, {
    title: '【BK】魔彩巧克力禮盒250g',
    imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/600876/2018/0324/158/b3fed03e-3cd8-40c7-b53d-19630adb2d31_t.jpg',
    price: 86,
}, {
    title: '【2件起售】樂(lè)奈烤巧克力72g',
    imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/131932/2017/1223/15/060b8ff9-674e-4869-9845-a8aee1f435a9_t.jpg',
    price: 22,
}, {
    title: '每日?qǐng)?jiān)果A款混合果仁果干孕婦零食堅(jiān)果小禮盒175克',
    imageUrl: 'https://a.vpimg4.com/upload/merchandise/pdcvis/602656/2018/0313/108/924c4a5b-7315-40bd-9d5f-84fb2fd489a2.jpg',
    price: 39,
}, {
    title: '每日?qǐng)?jiān)果A款混合果仁果干孕婦零食堅(jiān)果禮盒750克',
    imageUrl: 'https://a.vpimg2.com/upload/merchandise/pdcvis/2018/04/25/144/2a6462ca-bc0a-4ffb-9f43-d1e6fae63baf_235x297_90.jpg',
    price: 199,
}, {
    title: '鷹嘴豆250g',
    imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/602520/2018/0611/195/11f3c35b-12dc-4263-ad80-f2fa9a5b5c37_5t.jpg',
    price: 16,
}, {
    title: '【2件起售】蔓越莓干核桃仁118g',
    imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/602520/2018/0611/74/5b521a8e-2b51-41a4-b120-3e06e799be1b_5t.jpg',
    price: 28,
},
];

FlatListPage類(lèi)實(shí)現(xiàn)

export default class FlatListPage extends Component {

    static navigationOptions = ({navigation, screenProps}) => ({
        headerStyle: {
            backgroundColor: '#fff'
        },
        headerLeft: ( // 設(shè)置左邊的標(biāo)簽
            <XLImageButton
                imageStyle={appStyle.backIcon}
                clickAction={() => {
                    const {goBack} = navigation;
                    goBack();
                }}
            />
        ),
        headerTitle: (
            <NavigationBarTitle title={'FlatList'}/>
        ),
    });
    constructor(props) {
        super(props);
        this.state = {
            data: [],
            isRefreshing: false,
            isShowLoadMore: false,
        }
    }
    render() {
        return (
            <View style={styles.container}>
                <FlatList
                    style={{flex: 1}}
                    data={this.state.data}
                    numColumns={column}
                    horizontal={false}
                    //注意參數(shù)名:item  是固定的
                    renderItem={({item, index}) => {
                        return <TouchableOpacity
                            style={styles.cellStyle}
                            onPress={() => {
                                Alert.alert(item.title);
                            }}
                            opacity={0.5}
                        >
                            <View style={{flex: 1, alignItems: 'center'}}>
                                <Image style={{width: window.width / (column + 1), height: window.width / (column + 1)}}
                                       source={{uri: item.imageUrl}}/>
                                <Text numberOfLines={1}
                                      style={[styles.titleStyle, {textAlign: 'left'}]}>{item.title}</Text>
                                <Text style={styles.priceStyle}>{'¥' + item.price}</Text>
                            </View>

                        </TouchableOpacity>
                    }}
                    refreshControl={
                        <RefreshControl
                            tintColor="#ff0000"
                            title="Loading..."
                            titleColor="#00ff00"
                            colors={['#ff0000', '#00ff00', '#0000ff']}
                            progressBackgroundColor="#ffff00"
                            refreshing={this.state.isRefreshing}
                            onRefresh={() => {
                                this.setState({isRefreshing: true});
                                setTimeout(() => {
                                    this.setState({
                                        isRefreshing: false,
                                        data: list,
                                    });
                                }, 2000);
                            }}/>
                    }
                    ListEmptyComponent={() => {
                        return <View style={[styles.container, {alignItems: 'center'}]}>
                            <Text style={styles.noDataText}>暫無(wú)數(shù)據(jù)...</Text>
                        </View>
                    }}
                    onEndReachedThreshold={0.1}//當(dāng)前可視列表高度的十分之一
                    onEndReached={(info: { distanceFromEnd: number }) => {
                        if (this.state.data.length > 30 || this.state.isShowLoadMore) {//控制是否還有更多可加載
                            return null;
                        }
                        this.setState({
                            isShowLoadMore: true,//顯示加載更多指示器
                        }, function (finish) {
                            //拼接數(shù)據(jù)
                            const data = this.state.data.concat(list);
                            setTimeout(() => {
                                this.setState({
                                    data: data,
                                }, function (finish) {
                                    this.setState({
                                        isShowLoadMore: false,
                                    })
                                });
                            }, 2000);
                        })
                    }}
                    ListFooterComponent={() => {
                        return this.state.isShowLoadMore ? <View style={styles.indicator}>
                            <ActivityIndicator
                                color={'#f00'}
                                size={'small'}
                            />
                        </View> : null
                    }}
                />
            </View>
        )
    }
}

本文件樣式

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
    },
    lineStyle: {
        flex: 1,
        height: 0.5,
        backgroundColor: '#999',
    },
    cellText: {
        lineHeight: 44,
        marginHorizontal: 15,
        color: '#666',
    },
    headerStyle: {
        height: 40,
        justifyContent: 'center',
        paddingHorizontal: 10,
        backgroundColor: "#ffead1"
    },
    cellStyle: {
        marginVertical: 10,
        width: window.width / column,
    },
    titleStyle: {
        padding: 5,
        color: '#666',
    },
    priceStyle: {
        color: '#f00',
        paddingHorizontal: 5,
        // textDecorationLine: 'line-through',//刪除線(xiàn)
    },
    indicator: {
        height: 30,
        alignItems: 'center',
        justifyContent: 'center',
    },
    noDataText: {
        color: '#666',
        lineHeight: 50
    }
});

XLButton 文件實(shí)現(xiàn)

/*
* 自定義組件:按鈕
*
* */
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Image, StyleSheet, Text, TouchableOpacity,} from 'react-native';
//文字按鈕
export class XLButton extends Component {

    static defaultProp = {
        title: 'button',//標(biāo)題
        color: '#333',//字體顏色
        titleStyle: null,//標(biāo)題風(fēng)格text
        textAlign: 'center',//文字居中
        fontSize: 15,//字體大小
        backgroundColor: 'rgba(0,0,0,0)',//背景顏色
        borderRadius: 0,//背景圓角
        borderColor: '#fff',//邊框顏色
        borderWidth: 0,//邊框?qū)挾?        backgroundStyle: null,//背景風(fēng)格
        clickAction: null,//事件點(diǎn)擊
        tag: 0,//索引標(biāo)記
        data: null,//數(shù)據(jù)項(xiàng)
    };
    static propTypes = {
        title: PropTypes.string,//標(biāo)題
        color: PropTypes.string,//字體顏色
        fontSize: PropTypes.number,//字體大小
        textAlign: PropTypes.string,//文字居中
        borderRadius: PropTypes.number,//背景圓角
        borderColor: PropTypes.string,//邊框顏色
        borderWidth: PropTypes.number,//邊框?qū)挾?        clickAction: PropTypes.func,//事件點(diǎn)擊
        tag: PropTypes.number,//索引標(biāo)記
        data: PropTypes.any,//數(shù)據(jù)項(xiàng)
    };
    render() {
        return (
            <TouchableOpacity
                style={[{
                    backgroundColor: this.props.backgroundColor,
                    borderWidth: this.props.borderWidth,
                    borderColor: this.props.borderColor,
                    borderRadius: this.props.borderRadius
                }, this.props.backgroundStyle ? this.props.backgroundStyle : null]}
                onPress={() => {
                    if (this.props.clickAction) {
                        this.props.clickAction(this.props.tag, this.props.data);
                    }
                }}
            >
                <Text style={[{
                    color: this.props.color,
                    fontSize: this.props.fontSize,
                    textAlign: this.props.textAlign
                },
                    this.props.titleStyle ? this.props.titleStyle : null]}
                >{this.props.title}</Text>

            </TouchableOpacity>
        );
    }
}
//圖片按鈕
export class XLImageButton extends XLButton {
    static defaultProp = {
        image: null,
        imageUrl: null,
        imageStyle: null,
    };
    static propTypes = {
        image: PropTypes.object,
        imageUrl: PropTypes.number,
    };
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <TouchableOpacity
                style={[{
                    backgroundColor: this.props.backgroundColor,
                    borderWidth: this.props.borderWidth,
                    borderColor: this.props.borderColor,
                    borderRadius: this.props.borderRadius
                }, this.props.backgroundStyle ? this.props.backgroundStyle : null]}
                onPress={() => {
                    if (this.props.clickAction) {
                        this.props.clickAction(this.props.tag, this.props.data);
                    }
                }}
            >
                <Image style={[this.props.imageStyle ? this.props.imageStyle : styles.imageIcon]}
                       source={this.props.imageUrl ? {uri: this.props.imageUrl} :
                           this.props.image ? this.props.image : require('../../res/nav/navBack.png')}
                />
            </TouchableOpacity>
        );
    }
}
const styles = StyleSheet.create({
    imageIcon: {
        width: 10,
        height: 18,
        marginHorizontal: 10,
        marginVertical: 5,
    }
});

公用導(dǎo)航欄適配:NavigationBarTitle

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Text, View,} from 'react-native';
import {appStyle} from "../style/BaseStyles";

export class NavigationBarTitle extends Component {
    static defaultProp = {
        title: 'title',//標(biāo)題
    };
    static propTypes = {
        title: PropTypes.string,//標(biāo)題
    };
    render() {
        return (
            <View style={appStyle.headerTitleStyle}>
                <Text style={appStyle.navTitleStyle}>{this.props.title}</Text>
            </View>
        );
    }
}

通用樣式文件:BaseStyles

import {StyleSheet,Dimensions} from 'react-native';
const window = Dimensions.get('window');

export const appStyle = StyleSheet.create({
    backIcon: {
        width: 10,
        height: 18,
        marginHorizontal: 15,
    },
    baseTextColor: {
        color: '#FE6634',
    },
    navTitleStyle:{
       fontSize:17,
        fontWeight:'bold',
       color:'#333',
       textAlign:'center',
    },
    viewBGColor:{
        backgroundColor:'#f5f5f5',
    },
    headerTitleStyle:{
        width:window.width-120,
        justifyContent:'center',
    },
});

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末徘键,一起剝皮案震驚了整個(gè)濱河市汤徽,隨后出現(xiàn)的幾起案子所灸,更是在濱河造成了極大的恐慌棵红,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畏铆,死亡現(xiàn)場(chǎng)離奇詭異投慈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)妈倔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)博投,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人盯蝴,你說(shuō)我怎么就攤上這事毅哗。” “怎么了捧挺?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵虑绵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我闽烙,道長(zhǎng)翅睛,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任黑竞,我火速辦了婚禮捕发,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘很魂。我一直安慰自己扎酷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布遏匆。 她就那樣靜靜地躺著法挨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪幅聘。 梳的紋絲不亂的頭發(fā)上凡纳,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音帝蒿,去河邊找鬼荐糜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陵叽,可吹牛的內(nèi)容都是我干的狞尔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼巩掺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼偏序!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起胖替,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤研儒,失蹤者是張志新(化名)和其女友劉穎豫缨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體端朵,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡好芭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了冲呢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舍败。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖敬拓,靈堂內(nèi)的尸體忽然破棺而出邻薯,到底是詐尸還是另有隱情,我是刑警寧澤乘凸,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布厕诡,位于F島的核電站,受9級(jí)特大地震影響营勤,放射性物質(zhì)發(fā)生泄漏灵嫌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一葛作、第九天 我趴在偏房一處隱蔽的房頂上張望寿羞。 院中可真熱鬧,春花似錦赂蠢、人聲如沸稠曼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至漠吻,卻和暖如春量瓜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背途乃。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工绍傲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耍共。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓烫饼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親试读。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杠纵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容