1.因为需要定时器,所以我们要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]}>•</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,
Platform,
} 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 (
<View style={styles.container}>
{/*导航条*/}
{this.renderNavBar()}
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderHeader={this.renderHeader}
/>
</View>
);
}, // 导航条
renderNavBar(){
return(
<View style={styles.navOutViewStyle}>
<Text style={{color:'white',fontSize:16,fontWeight:'bold'}}>首页</Text>
</View>
)
}, // 返回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({
// 导航条视图
navOutViewStyle:{
height:Platform.OS === 'ios' ? 64 : 44,
backgroundColor:'#468AFF',
// 主轴方向
flexDirection:'row',
// 侧轴对齐方式 垂直居中
alignItems:'center',
// 主轴方向居中
justifyContent:'center',
},
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
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.效果图

react-native 项目实战 -- 新闻客户端(6) -- 完善ListView头部视图的更多相关文章

  1. 【腾讯Bugly干货分享】React Native项目实战总结

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...

  2. React Native 项目实战-Tamic

    layout: post title: React Native 项目实战 date: 2016-10-18 15:02:29 +0800 comments: true categories: Rea ...

  3. react-native 项目实战 -- 新闻客户端(5) -- 完善首页列表数据

    1.Home.js: /** * 首页 */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, T ...

  4. react-native 项目实战 -- 新闻客户端(7) -- 新闻详情页

    http://c.3g.163.com/nc/article/BUH64L0J00031H2L/full.html 观察这个地址,BUH64L0J00031H2L 就是每条新闻数据里的postid.  ...

  5. React Native 项目实战 -- DoubanProject

    引言:本文是我研究react-native时写的一个简单的demo,代码里有详细的注释,好废话不多说,直接上代码. 1.项目目录 2.index.android.js /** * index.andr ...

  6. React Native项目实战

    算是学习React Native的一次项目总结吧,目的还是提高自己. 包含的内容: 1>仿"美团"页面的实现; 2>封装项目中和自己常用的一些组件; 3>学习别人 ...

  7. react-native 项目实战 -- 新闻客户端(4) -- 请求网络数据

    1.Home.js /** * 首页 */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Te ...

  8. react-native 项目实战 -- 新闻客户端(2) -- 完善TabBar

    1.创建 drawable-xxhdpi 文件夹,保存 TabBar 的 icon图标 android  --  app  --  src  --  main  --  res  --  drawab ...

  9. react-native 项目实战 -- 新闻客户端(3) -- 包装导航控制器

    1.修改后的 Main.js /** * 主页面 */ import React, { Component } from 'react'; import { StyleSheet, Text, Vie ...

随机推荐

  1. VC版本与VS版本 对照表

    Microsoft Visual Studio 6.0                  VC6.0 Microsoft Visual Studio .NET 2002:          VC7.0 ...

  2. (2) python--pandas

    import pandas as pd import numpy as np # 创建的Series几种方式 s1 = pd.Series(range(4)) s2 = pd.Series([0, 1 ...

  3. python mysql创建表

    表设计 表:student 字段名 类型 是否为空 主键 描述 StdID int 否 是 学生ID StdName varchar(100) 否 学生姓名 Gender enum('M','F') ...

  4. pymongo.errors.BulkWriteError错误排解

    在mongodb进行数据库操作的时候触发异常   pymongo Error: pymongo.errors.BulkWriteError: batch op errors occurred 这种问题 ...

  5. Visual Studio跨平台开发(3):Xamarin iOS多页面应用开发

    前言 在前一篇教学中, 我们学会如何使用Visual Studio 搭配Xcode进行iOS基本控制项的操作. 但都是属于单一画面的应用程式. 这次我们要来练习如何通过Navigation Contr ...

  6. ASP.NET增加微信公众号功能

    最近微信的公众号使用的挺多的.我们也弄了个,现在有个需求就是在用户点击菜单的时候,获取用户的OPENID,然后作为后续使用. 首先记录下步骤, 安装必要的dll引用 install-package s ...

  7. J.U.C并发框架源码阅读(十三)ThreadPoolExecutor

    基于版本jdk1.7.0_80 java.util.concurrent.ThreadPoolExecutor 代码如下 /* * ORACLE PROPRIETARY/CONFIDENTIAL. U ...

  8. 第十四届华中科技大学程序设计竞赛 J Various Tree【数值型一维BFS/最小步数】

    链接:https://www.nowcoder.com/acm/contest/106/J 来源:牛客网 题目描述 It's universally acknowledged that there'r ...

  9. Python的Web编程[0] -> Web客户端[0] -> 统一资源定位符 URL

    统一资源定位符 / URL 目录 URL 构成 URL 解析 URL 处理 1 URL构成 统一资源定位符(Uniform Resource Locator) 是对可以从互联网上得到的资源的位置和访问 ...

  10. tyvj——P1002 谁拿了最多奖学金

      P1002 谁拿了最多奖学金 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2005复赛提高组第一题 描述 某校的惯例是在每学期的期末考试之后发 ...