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. Linux Mint---开启桌面三维特效

    其实系统默认已经安装好了compiz,我们只需要切换就可以了 menu->control center->desktop setting->window 开启compiz的时候,由于 ...

  2. artDialog组件与iframe

    背景 组件官网. 未用过的朋友可以先了解下. 当Content参数传递html元素时,官方的解释是: 备注:1.元素不是复制而是完整移动到对话框中,所以原有的事件与属性都将会保留 2.如果隐藏元素被传 ...

  3. calc(NOIP模拟赛Round 3)

    原题: D e s c r i p t i o n 给三个正整数n,m和p,求(n^1+...n^m) mod p. Input 一行,三个整数n,m和p. Output 输出答案. S a m p ...

  4. windows编程中的数据类型

    在windows编程中,有许多奇怪的数据类型,初学者不知道这些代表什么,下面就把一些数据类型列出如下: ATOM 原子(原子表中的一个字符串的参考) BOOL 布尔变量 BOOLEAN 布尔变量 BY ...

  5. Appium+python自动化2-环境搭建(下)【转载】

    前言    上一篇android测试开发环境已经准备好, 接下来就是appium的环境安装了.环境安装过程中切勿浮躁,按照步骤一个个来. 环境装好后,可以用真机连电脑,也可以用android-sdk里 ...

  6. 我为什么喜欢Go语言

    从2000年至今,也写了11年代码了,期间用过VB.Delphi.C#.C++.Ruby.Python,一直在寻找一门符合自己心意和理念的 语言.我很在意写代码时的手感和执行的效率,所以在Go出现之前 ...

  7. SPRING CLOUD服务网关之ZUUL

    服务网关是微服务架构中一个不可或缺的部分.通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由.均衡负载功能之外,它还具备了权限控制等功能.Spring Cloud Netflix中 ...

  8. (22)C#windows打包部署

    程序做好后需要打包部署后才能使用 一.创建安装项目 解决方案右键-添加-新建项目-其他项目类型-安装和部署-双击进入文件系统. 二.制作安装程序 一个完整的安装程序包括项目输出文件.内容文件.桌面快捷 ...

  9. UVA 437 巴比伦塔 【DAG上DP/LIS变形】

    [链接]:https://cn.vjudge.net/problem/UVA-437 [题意]:给你n个立方体,让你以长宽为底,一个个搭起来(下面的立方体的长和宽必须大于上面的长和宽)求能得到的最长高 ...

  10. SSOJ 2316 面积【DFS/Flood Fill】

    题目描述 编程计算由“1”号围成的下列图形的面积.面积计算方法是统计1号所围成的闭合曲线中点的数目. 如图所示,在10*10的二维数组中,“1”围住了15个点,因此面积为15. 题目大意:对于给定的1 ...