ReactNative 项目实战 (2) ListView 使用 网络请求以及下拉刷新 (条目控件封装)

看我的其他系列的文章
React_Native 项目实战 (1) (首页,以及页面的切换)

https://github.com/liudao01/ReactNativeProject
github地址 还在更新中

ListView 使用 网络请求以及下拉刷新

最终实现的效果图
mark

listview 以及 最热页面内容切换

现在写页面的内容 ,

知识点:

  • listivew 的使用
  • 网络数据的获取
  • 页面内容的组件封装

Listtview 的使用 看官方文档
http://reactnative.cn/docs/0.48/listviewdatasource.html#content

不要忘记引入ListView

下面是使用本地数据做的listview

mark

下面是代码


/**
 * Created by liuml on 2017/9/11.
 */
import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Image,
    ListView,
    RefreshControl
}from 'react-native';

import NavigationBar from "../compoent/NavigationBar.js"
import ScrollableTabView from "react-native-scrollable-tab-view"
import ProjectRow from "../compoent/ProjectRow"
export default class PapularPage extends Component {


    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            languages: ["Android", "Ios", "Java", "React", "JS"]
        };
    }


    render() {
        return <View style={styles.container}>
            <NavigationBar/>
            <ScrollableTabView
                tabBarBackgroundColor="#63B8FF"
                tabBarActiveTextColor="#FFF"
                tabBarInactiveTextColor="#F5FFFA"
                tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}>
                {
                    this.state.languages.map((item, i) => {
                        return <PopularTab key={`tab${i}`} tabLabel={item}/>
                    })
                }
            </ScrollableTabView>
        </View> 
    }
}

class PopularTab extends Component {

    //这里是Tab 的名字
    static defaultProps = {
        tabLable: 'Android',
    }
    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})//是一个优化,节省无用的UI渲染 判断前后数据是否改变 如果改变就更新
        };
    }

    componentDidMount() {
        this.setState({
                dataSource: this.state.dataSource.cloneWithRows(['first', 'second', 'three'])
            }
        )
    };

    renderRow = () => {
        return <Text>test</Text>
    }


    render() {
        return <View style={styles.container}>
            <ListView
                dataSource={this.state.dataSource}
                renderRow={this.renderRow}
            ></ListView>
        </View>
    }


}


const styles = StyleSheet.create({
    container: {
        flex: 1
    }
});

解释下

componentDidMount

这个是RN加载完毕后调用的方法 生命周期

我在这里给他设置了列表的假数据 只有三条 所以在上面可以看到三条数据

其他的没什么 了 Listview的使用可以看下官方文档 比我讲的清楚

http://reactnative.cn/docs/0.48/listviewdatasource.html#content

联网请求数据返回给listview设置数据

mark

下面是代码

/**
 * Created by liuml on 2017/9/11.
 */
import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Image,
    ListView,
    RefreshControl
}from 'react-native';

import NavigationBar from "../compoent/NavigationBar.js"
import ScrollableTabView from "react-native-scrollable-tab-view"
import ProjectRow from "../compoent/ProjectRow"
export default class PapularPage extends Component {


    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            languages: ["Android", "Ios", "Java", "React", "JS"]
        };
    }


    render() {
        return <View style={styles.container}>
            <NavigationBar/>
            <ScrollableTabView
                tabBarBackgroundColor="#63B8FF"
                tabBarActiveTextColor="#FFF"
                tabBarInactiveTextColor="#F5FFFA"
                tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}>
                {
                    this.state.languages.map((item, i) => {
                        return <PopularTab key={`tab${i}`} tabLabel={item}/>
                    })
                }
            </ScrollableTabView>
        </View>
    }
}

class PopularTab extends Component {

    //这里是Tab 的名字
    static defaultProps = {
        tabLabel: 'android',
    }
    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})//是一个优化,节省无用的UI渲染 判断前后数据是否改变 如果改变就更新
        };
    }

    /*componentDidMount() {
     /!*this.setState({
     dataSource: this.state.dataSource.cloneWithRows(['first', 'second', 'three'])
     }
     )*!/
     this.loadData();
     };*/

    //和上面一样的效果
    componentDidMount = () => {
        this.loadData();
    }

    //渲染ListView的每一行
    renderRow = (obj) => {
        // return <ProjectRow>{obj.full_name}</ProjectRow>
        return <Text>{obj.full_name}</Text>
    }


    //加载数据
    loadData = () => {

        fetch(`https://api.github.com/search/repositories?q=${this.props.tabLabel}&sort=stars`)
            .then(response => response.json()) //服务器响应response对象,继续变成json对象
            .then(json => {
                //更新dataSource
                this.setState({
                    dataSource: this.state.dataSource.cloneWithRows(json.items)

                });
            })
            .catch((error) => {
                console.error(error);
            }).done();
    }

    render() {
        return <View style={styles.container}>
            <ListView
                dataSource={this.state.dataSource}
                renderRow={this.renderRow}
            ></ListView>
        </View>
    }
}


const styles = StyleSheet.create({
    container: {
        flex: 1
    }
});

联网请求 看官方文档

http://reactnative.cn/docs/0.48/network.html#content

这样就做好了上面的gif图的效果

Listview 的item ProjectRow.js

现在数据有了,下面是做item的样式 把数据显示到item上面

先看下效果图

mark

  • 本地的数据 我把item 抽取出来 做成一个组件了

下面是item组件

/**
 * Created by liuml on 2017/9/14.
 */

import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    StatusBar,
    Platform,
    Image,
    TouchableOpacity
} from 'react-native';

export default class ProjectRow extends Component {

    static defaultProps = {
        item: {}
    }


    render() {
        var item = this.props.item;
        return <View style={styles.container}>
            <Text style={styles.title}>{item.full_name}</Text>
            <Text style={styles.description}>{item.description}</Text>
            <View style={styles.bottom}>
                <View style={styles.bottomTextWrapper}>
                    <Text>作者:</Text>
                    {console.log(item.owner.avatar_url)}
                    <Image style={{width: 22, height: 22}} source={{uri: item.owner.avatar_url}}/>
                </View>
                <View style={styles.bottomTextWrapper}>
                    <Text>star:</Text>
                    <Text>{item.stargazers_count}</Text>
                </View>
                <Image source={require("../../res/images/ic_unstar_transparent.png")} style={{width: 22, height: 22}}/>
            </View>
        </View>
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        padding: 10,
        marginLeft: 5,
        marginRight: 5,
        marginVertical: 5,
        backgroundColor: '#FFF',
        flexDirection: 'column',
        borderColor: '#dddddd',
        borderWidth: 0.5,
        borderRadius: 2,
        shadowColor: 'gray',
        shadowOffset: {width: 0.5, height: 0.5},
        shadowRadius: 1, //阴影半径
        shadowOpacity: 0.4,
        elevation: 2 //Android 投影

    },
    title: {
        fontSize: 16

    },
    description: {
        fontSize: 14,
        marginBottom: 2,
        color: '#757575'

    },
    bottom: {
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'space-between'
    },
    bottomTextWrapper: {
        flexDirection: 'row',
        alignItems: 'center'
    }
})

解释下: 没啥好说的 就是UI布局 做多了都一样 下面是几个属性 解释下

borderColor : 设置边框颜色

borderWidth : 属性设置所有四个边框的宽度。

borderRadius : 边框圆角效果

shadowColor:‘gray’,//阴影颜色

shadowOffset:{width:0.5,height:0.5},//shadowoffset 四周阴影

shadowRadius:1, //阴影半径

shadowOpacity:0.4,//阴影不透明度

elevation:2 //Android 投影

还有就是PopularPage.js 里面只改动了一行代码

    //渲染ListView的每一行
    renderRow = (obj) => {
        return <ProjectRow item={obj}></ProjectRow>
        // return <Text>{obj.full_name}</Text>
    }

这样就做好了上面的gif图的效果

listview 的加载动画以及下拉刷新

看下文档

https://reactnative.cn/docs/0.48/refreshcontrol.html#content

搜索 RefreshControl 这个就是刷新的使用


/**
 * Created by liuml on 2017/9/11.
 */
import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Image,
    ListView,
    RefreshControl
}from 'react-native';

import NavigationBar from "../compoent/NavigationBar.js"
import ScrollableTabView from "react-native-scrollable-tab-view"
import ProjectRow from "../compoent/ProjectRow"
export default class PapularPage extends Component {


    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            languages: ["Android", "Ios", "Java", "React", "JS"]
        };
    }


    render() {
        return <View style={styles.container}>
            <NavigationBar/>
            <ScrollableTabView
                tabBarBackgroundColor="#63B8FF"
                tabBarActiveTextColor="#FFF"
                tabBarInactiveTextColor="#F5FFFA"
                tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}>
                {
                    this.state.languages.map((item, i) => {
                        return <PopularTab key={`tab${i}`} tabLabel={item}/>
                    })
                }
            </ScrollableTabView>
        </View>
    }
}

class PopularTab extends Component {

    //这里是Tab 的名字
    static defaultProps = {
        tabLabel: 'android',
    }
    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),//是一个优化,节省无用的UI渲染 判断前后数据是否改变 如果改变就更新
            isLoading: true
        };
    }

    /*componentDidMount() {
     /!*this.setState({
     dataSource: this.state.dataSource.cloneWithRows(['first', 'second', 'three'])
     }
     )*!/
     this.loadData();
     };*/

    //和上面一样的效果
    componentDidMount = () => {
        this.loadData();
    }

    //渲染ListView的每一行
    renderRow = (obj) => {
        return <ProjectRow item={obj}></ProjectRow>
        // return <Text>{obj.full_name}</Text>
    }


    //加载数据
    loadData = () => {
        this.setState({isLoading: true});
        fetch(`https://api.github.com/search/repositories?q=${this.props.tabLabel}&sort=stars`)
            .then(response => response.json()) //服务器响应response对象,继续变成json对象
            .then(json => {
                //更新dataSource
                this.setState({
                    dataSource: this.state.dataSource.cloneWithRows(json.items),
                    isLoading: false,
                });
            })
            .catch((error) => {
                console.error(error);
            }).done();
    }

    handleRefresh = () => {
        this.loadData();
    }

    render() {
        return <View style={styles.container}>
            <ListView
                dataSource={this.state.dataSource}
                renderRow={this.renderRow}
                refreshControl={
                    <RefreshControl
                        refreshing={this.state.isLoading}
                        tintColor="#63B8FF"
                        title="正在加载..."
                        titleColor="#63B8FF"
                        colors={['#63B8FF']}
                    />
                }
            ></ListView>
        </View>
    }
}


const styles = StyleSheet.create({
    container: {
        flex: 1
    }
});

解释

  • isLoading 用来判断是否显示对话框
  • return 是把每个item的数据传到 ProjectRow里面去

最终实现的效果图
mark

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值