新闻客户端06 - 完善ListView头部视图

1.我们之前已经用scrollView实现了轮播图效果
地址1地址2
因为需要定时器,所以我们要cd到当前项目根目录下安装这个类库:

npm i react-timer-mixin --save  

这里写图片描述

2、Component/ScrollImage.js

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

// 引入Dimensions类库
var Dimensions = require('Dimensions');
var ScreenW = Dimensions.get('window').width;

// 引入计时器类库
var TimerMixin = require('react-timer-mixin');

var ScrollImage = React.createClass({
    // 注册计时器
    mixins: [TimerMixin],

    // 设置固定值
    getDefaultProps(){
        return{
            // 每隔多少时间
            duration:2000,
            // 所有的image对象数据
            imageDataArr:[]
        }
    },

    // 设置可变和初始化值
    getInitialState(){
        return{
            // 当前页面
            currentPage:0,
            // 当前标题
            title:this.props.imageDataArr[0].title,
        }
    },

    render() {
        return (
            <View style={styles.container}>
                <ScrollView
                    ref="scrollView"
                    horizontal={true}
                    pagingEnabled={true}
                    showsHorizontalScrollIndicator={false}
                    // 当一帧滚动结束
                    onMomentumScrollEnd={(e)=>this.onAnimationEnd(e)}
                    // 开始拖拽scrollView
                    onScrollBeginDrag={this.onScrollBeginDrag}
                    // 停止拖拽
                    onScrollEndDrag={this.onScrollEndDrag}
                >
                    {this.renderAllImage()}
                </ScrollView>
                <View style={styles.indicatorViewStyle}>
                    <Text style={{color:'white',marginLeft:10}}>{this.state.title}</Text>
                    <View style={{flexDirection:'row',alignItems:'center',marginRight:10}}>
                        {this.renderPageCircle()}
                    </View>
                </View>
            </View>
        );
    },

    // 开始拖拽的时候调用
    onScrollBeginDrag(){
        // 停止定时器
        this.clearInterval(this.timer);
    },

    // 停止拖拽的时候调用
    onScrollEndDrag(){
        // 开启定时器
        this.startTimer();
    },

    // 组件已经加载完毕之后,实现一些复杂的操作
    componentDidMount(){
        // 开启定时器
        this.startTimer();
    },

    // 开启定时器
    startTimer(){
        // 1.拿到scrollView
        var scrollView = this.refs.scrollView;
        var imgCount = this.props.imageDataArr.length;

        // 2.添加定时器 this.timer 可以理解成一个隐士的全局变量
        this.timer = this.setInterval(function () {
            // 2.1设置圆点
            var activePage = 0;
            // 2.2判断
            if((this.state.currentPage+1) >= imgCount){ //越界
                activePage = 0;
            }else{
                activePage = this.state.currentPage+1;
            }
            // 3.更新状态机,重新绘制UI
            this.setState({
                currentPage:activePage
            });

            //4.让scrollView滚动起来
            var offsetX = activePage * ScreenW;
            scrollView.scrollResponderScrollTo({x:offsetX,y:0,animated:true});
        },this.props.duration);
    },

    // 返回图片
    renderAllImage(){
        // 数组
        var allImage = [];
        // 拿到图片数据
        var imageArr = this.props.imageDataArr;
        // 遍历
        for(var i=0;i<imageArr.length;i++){
            // 取出单个图片对象
            var imgItem = imageArr[i];
            // 创建组件装入数组
            allImage.push(
                <Image key={i} source={{uri:imgItem.imgsrc}} style={{width: ScreenW,height:150}} />
            );
        }

        // 返回
        return allImage;
    },

    // 返回分页指示器圆点
    renderPageCircle(){
        // 定义一个数组放置所有的圆点
        var indicatorArr = [];
        var imgArr = this.props.imageDataArr;

        // 特殊样式
        var style;

        for(var i=0;i<imgArr.length;i++){
            // 判断style
            style = (i==this.state.currentPage) ? {color:'orange'} : {color:'#fff'};
            indicatorArr.push(
                <Text key={i} style={[{fontSize:30},style]}>&bull;</Text>
            );
        }
        return indicatorArr;
    },

    // 当一帧滚动结束的时候调用
    onAnimationEnd(event){
        // 1.计算水平方向偏移量
        var offsetX = event.nativeEvent.contentOffset.x
        // 2.计算当前页码
        var page = Math.floor(offsetX / ScreenW);
        // 3.更新状态机,重新绘制UI
        this.setState({
            currentPage:page,
            title:this.props.imageDataArr[page].title,
        });
    },

});

const styles = StyleSheet.create({
    container:{
        // marginTop:20,
    },
    // 分页指示器样式
    indicatorViewStyle:{
        width:ScreenW,
        height:25,
        backgroundColor:'rgba(0,0,0,0.4)',
        position:'absolute',
        bottom:0,
        // 设置主轴方向,让圆点水平排列
        flexDirection:'row',
        // 侧轴方向
        alignItems:'center',
        // 主轴对齐方式
        justifyContent:'space-between',
    }
});

// 最后要输出这个类库
module.exports = ScrollImage;

3、Home.js

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

// 引入Dimensions类库
var Dimensions = require('Dimensions');
var ScreenW = Dimensions.get('window').width;

// 导入本地json数据
var LocalData = require('../LocalData.json');

// 导入外部的组件类
var ScrollImage = require('../Component/ScrollImage');

var Home = React.createClass({
    // 不可改变的默认值
    getDefaultProps(){
        return{
            url_api:'http://c.m.163.com/nc/article/headline/T1348647853363/0-20.html',
            key_word:'T1348647853363'
        }
    },

    // 初始化
    getInitialState(){
        return{
            // ListView头部轮播图的数据源
            headerDataArr:[],
            // cell的数据源
            dataSource: new ListView.DataSource({
                rowHasChanged:(r1,r2)=>{r1 !== r2}
            })
        }
    },

    render() {
        return (
            <ListView
                dataSource={this.state.dataSource}
                renderRow={this.renderRow}
                renderHeader={this.renderHeader}
            />
        );
    },

    // 返回ListView头部视图
    renderHeader(){
        // 如果没有头部banner数据
        if(this.state.headerDataArr.length == 0) return;

        return(
            <ScrollImage
                imageDataArr={this.state.headerDataArr}
            />
        )
    },

    // 返回LisView中的单个cell
    renderRow(rowData){
        return(
            <TouchableOpacity activeOpacity={0.8}>
                <View style={styles.cellViewStyle}>
                    <Image source={{uri:rowData.imgsrc}} style={styles.imgStyle} />
                    <View style={styles.rightViewStyle}>
                        <Text style={styles.mainTitleStyle}>{rowData.title}</Text>
                        <Text style={styles.subTitleStyle}>{rowData.digest}</Text>
                    </View>
                </View>
            </TouchableOpacity>
        )
    },

    // 组件加载完毕之后调用
    componentDidMount(){
        // 请求网络数据
        this.loadDataFromNet();
    },

    // 请求网络数据的方法
    loadDataFromNet(){
        fetch(this.props.url_api)
            .then((response)=>response.json())
            .then((responseData)=>{
                // 拿到需要的数据
                var jsonData = responseData[this.props.key_word];

                // 处理数据
                this.dealWithData(jsonData);
            })
            .catch((error)=>{
                if(error){
                   // 网络请求失败,就用本地数据
                    console.log('网络请求失败');
                    var jsonData = LocalData[this.props.key_word];
                    this.dealWithData(jsonData);
                }
            })
    },

    // 处理网络数据的细节方法
    dealWithData(jsonData){
        // 定义临时变量
        var headerArr = [], listDataArr = [];
        // 遍历拿到的json数据
        for (var i=0;i<jsonData.length;i++){
            // 取出单个对象
            var data = jsonData[i];
            if(data.hasAD == 1){
                // 取出广告数据
                headerArr = data.ads;
            }else {
                // 非广告数据(行数据)
                listDataArr.push(data)
            }
        }

        // 更新状态机
        this.setState({
            // ListView头部轮播图的数据源
            headerDataArr:headerArr,
            // cell的数据源
            dataSource:this.state.dataSource.cloneWithRows(listDataArr),
        });

        console.log(headerArr,listDataArr);
    },
});

const styles = StyleSheet.create({
    cellViewStyle:{
        // 主轴方向
        flexDirection:'row',
        padding:10,
        // 设置下边框
        borderBottomColor:'#e8e8e8',
        borderBottomWidth:0.8,
    },
    imgStyle:{
        width:90,
        width:90,
        backgroundColor:'gray',
    },
    rightViewStyle:{
        width:ScreenW - 90 - 10 * 2,
        marginLeft:10,
    },
    mainTitleStyle:{
        fontSize:16,
        marginBottom:5,
    },
    subTitleStyle:{
        fontSize:14,
        color:'gray',
    },
});

// 输出类
module.exports = Home;

4.演示效果
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值