代码地址如下:
http://www.demodashi.com/demo/13212.html

标签与内容页联动

上一节(React Native : 自定义视图)做到了点击标签自动移动,还差跟下面的视图进行联动。

首先创建 NewsList.js :

import React from 'react'
import {View,Text,ListView,Image,StyleSheet,Dimensions
} from 'react-native'
const {width, height} = Dimensions.get('window')export default class NewsList extends React.Component {render() {const {style} = this.propsreturn (<View style={[styles.view,style]}></View>)}
}const styles = StyleSheet.create({view: {flex: 1,backgroundColor:'red'}
})

然后在 Home.js 引入,再加入 ScrollView ,现在 Home.jsredner() 是这样子的,这里加入的 ScrollView 我们在后文中称为 NewsScrollView

render() {return (<View style={styles.view}><NavigationBar
                    title="首页"unLeftImage={true}/><SegmentedView
                    ref="SegmentedView"list={this.state.list}style={{height: 30}}/><ScrollView
                    style={styles.view}ref="ScrollView"horizontal={true}showsHorizontalScrollIndicator={false}pagingEnabled={true}>{ this._getNewsLists()}</ScrollView></View>)}

_getNewsLists() 方法:

_getNewsLists() {let lists = []if (this.state.list) {for (let index in this.state.list) {let dic = this.state.list[index]lists.push(<NewsList
                    key={index}style={{backgroundColor:'#' + this._getColor('',0), width: width, height: height - 49 - 64 - 30}}dic={dic}/>)}}return lists
}_getColor(color, index) {index ++if (index == 7) {return color}color = color + '0123456789abcdef'[Math.floor(Math.random()*16)]return  this._getColor(color, index)
}

根据返回的数据创建对应数量的视图,给随机颜色方便看效果。

先设置滑动 NewsScrollView 让标签跟着移动。

我们把 SegmentedViewitems.push 中的 onPress 方法的实现单独写到一个方法里,然后在这里调用:

_moveTo(index) {const { list } = this.props  //获取到 传入的数组this.state.selectItem && this.state.selectItem._unSelect()this.state.selectItem = this.refs[index]if (list.length > maxItem) {let meiosis = parseInt(maxItem / 2)this.refs.ScrollView.scrollTo({x: (index - meiosis < 0 ? 0 : index - meiosis > list.length - maxItem ? list.length - maxItem : index - meiosis ) * this.state.itemWidth, y: 0, animated: true})}
}

这里会发现我们给 this.state 加了一个 itemWidth ,原来我们获取 itemWidth 是在 _getItems() 中计算的,但是在渲染的过程中无法调用 setState() ,我们把计算 itemWidth 的方法移动到 :

componentWillReceiveProps(props) {const { list } = props  //获取到 传入的数组if (!list || list.length == 0) return// 计算每个标签的宽度let itemWidth = width / list.lengthif (list.length > maxItem) {itemWidth = width / maxItem}this.setState({itemWidth})
}

componentWillReceiveProps(props) 方法会在属性更新后调用,参数 props 是新的属性。

现在运行会发现点击标签可以正常改变标签的状态,然而拖动 NewsScrollView 只会让上一个选中的变为未选中,新的标签并没有变为选中,这是因为选中状态只在标签被点击的时候进行了设置,我们需要给 Item 添加一个选中的方法 :

 _select() {this.setState({isSelect: true})
}

然后在 _moveTo(index) 进行调用:

this.state.selectItem && this.state.selectItem._unSelect()
this.state.selectItem = this.refs[index]
this.state.selectItem._select()

现在运行滑动 NewsScrollView 上面的 SegmentedView 可以正常运行了。

最后设置点击标签可以让 NewsScrollView 滑动到对应的位置,我们需要给 SegmentedView 加入一个回调函数,在标签被点击的时候调用返回点击的 index

<SegmentedViewref="SegmentedView"list={this.state.list}style={{height: 30}}selectItem={(index) => {this.refs.ScrollView.scrollTo({x: width * index, y: 0, animated: true})}}
/>

SegmentedView 进行调用:

_getItems() {const { list, selectItem } = this.props  //获取到 传入的数组if (!list || list.length == 0) return []let items = []for (let index in list) {let dic = list[index]items.push(<Item
                ref={index}key={index}isSelect={index == 0}itemHeight={this.state.itemHeight}itemWidth={this.state.itemWidth}dic={dic}onPress={() => {this._moveTo(index)selectItem && selectItem(index)}}/>)}return items
}

加载新闻列表第一页数据 加载新闻列表第一页数据

Home.js 中已经给 NewsList 传入了数据,我们再给传入一个参数识别是否是第一页,初始只加载第一页的数据,也方便调试:

_getNewsLists() {let lists = []if (this.state.list) {for (let index in this.state.list) {let dic = this.state.list[index]lists.push(<NewsList
                    key={index}style={{backgroundColor:'white'}}dic={dic}isRequest={index == 0}/>)}}return lists
}

然后去 NewsList.js 进行请求数据:

// 构造
constructor(props) {super(props);// 初始状态this.state = {page: 1,rn: 1,};
}componentDidMount() {if (!this.props.isRequest) returnthis._onRefresh()
}_onRefresh(page) {if (this.props.dic) {let url = 'http://api.iapple123.com/newspush/list/index.html?clientid=1114283782&v=1.1&type='+ this.props.dic.NameEN+ '&startkey=&newkey=&index='+ (page ? page : this.state.page)+ '&size=20&ime=6271F554-7B2F-45DE-887E-4A336F64DEE6&apptypeid=ZJZYIOS1114283782&rn='+ this.state.rnLOG('url=》', url)fetch(url, {method: 'GET',headers: {'Accept': 'application/json','Content-Type': 'application/json',},}).then((res) => {res.json().then((json) => {LOG('GET SUCCESSED then =>', url, json)})}).catch((e) => {LOG('GET ERROR then =>', url, e)})}).catch((error) => {LOG('GET ERROR=>', url, '==>', error)})}
}

请求到数据后我们需要用 ListView (官方文档) 来显示, 所以导入 ListView ,然后去 render() 加入:

render() {const {style} = this.propsreturn (<View style={[styles.view,style]}><ListView
                style={{flex:1}}dataSource={this.state.dataSource} //设置数据源renderRow={this.renderRow} //设置cell/></View>)
}

然后加入 dataSourcerenderRow:

// 构造
constructor(props) {super(props);var getRowData = (dataBlob, sectionID, rowID) => {return dataBlob[sectionID][rowID]};// 初始状态this.state = {page: 1,rn: 1,dataSource: new ListView.DataSource({getRowData: getRowData,rowHasChanged: (r1, r2) => r1 !== r2,}),};this.renderRow = this.renderRow.bind(this)}renderRow(rowData, rowID, highlightRow) {return (<View />)
}

运行效果

我们要做的界面是这个样子

从上图可以看出来新闻分为 3 种样式,轮播图、有一张图片的和二、三张图片的。

接下来开始解析数据,解析完 json 数据发现只有一个数组,轮播图是取了前四个,剩下的根据 ImagesList 里图片的个数来判断,

.then((json) => { 加入

let list = json.NewsListlet swipers = []
let news = []for (let index in list) {let dic = list[index]index < 4 ? swipers.push(dic) : news.push(dic)
}news.splice(0, 0, swipers)this.setState({dataSource: this.state.dataSource.cloneWithRows(news)
})

现在 news 的数据结构为:

[[{},{}],{},{}
}

然后去 renderRow 处理数据

如果是数组,那么返回轮播图:

if (Object.prototype.toString.call(rowData) === '[object Array]') {return (<CarousePicture
            index={2}ref="ScrollView"rowData={rowData}style={{width, height: 200}}touchIn={this.props.touchIn}></CarousePicture>)
}

这里的轮播图本来用的 Swiper,但是在 Android 上有很多 BUG,我只好自己写了一个,但是在 Android 上的体验差强人意,源码在这里,把文件导入项目即可。

具体的可以看这里

touchIn 是由于在 Andoird 上两个 ScrollView 重叠时,处于顶部的 ScrollView 滑动事件不会响应,因为底部的 ScrollView 进行了响应并拦截了事件,我们需要在手指接触到轮播图的时候禁用底部 ScrollView 的滑动属性,再手指离开的时候再进行恢复,所以还需要去 Home.js 加入:

 _getNewsLists() {let lists = []if (this.state.list) {for (let index in this.state.list) {let dic = this.state.list[index]lists.push(<NewsList
                    key={index}style={{backgroundColor:'white', width: width, height: height - 64 - 49 - 30}}dic={dic}isRequest={index == 0}touchIn={(scrollEnabled) => {this.refs.ScrollView.setNativeProps({scrollEnabled: !scrollEnabled})}}/>)}}return lists
}

然后根据 ImagesList 的个数来区分:

let imagesList = rowData.ImagesListif (imagesList && imagesList.length == 1) {return (<TouchableOpacity style={{width,  backgroundColor:'white'}}><View
                style={{width, backgroundColor:'white', flexDirection:'row', justifyContent:'space-between', flex:1}}><Image
                    resizeMode="cover"style={{marginTop: 10, marginBottom:10, marginLeft: 10, width: 80, height: 80, backgroundColor:'#EEEEEE'}}source={{uri:imagesList[0].ImgPath}}/><View
                    style={{ marginRight: 10,backgroundColor:'white', marginTop: 10, height: 80, width: width - 110}}><Text>{rowData.Title}</Text><View style={{flex:1, flexDirection: 'row', justifyContent: 'space-between'}}><Text style={{marginTop:10, fontSize: 13, color: '#999999'}}>{rowData.Source}</Text><Text style={{marginRight:0,marginTop:10,fontSize: 13, color: '#999999'}}>{rowData.PublishTime}</Text></View></View></View><View style={{width, height:1, backgroundColor: '#EEEEEE'}}></View></TouchableOpacity>)
}let images = []for (let index in imagesList) {let dic = imagesList[index]images.push(<Image
            resizeMode="cover"key={index}style={{marginRight: 10, marginLeft: index == 0 ? 10 : 0, marginTop:10, marginBottom: 10,flex:1, height: 90}}source={{uri:dic.ImgPath}}/>)
}return (<TouchableOpacity style={{width,  backgroundColor:'white'}}><View style={{width,backgroundColor:'white'}}><Text style={{marginLeft: 10, marginTop: 10}}>{rowData.Title}</Text></View><View style={{flexDirection:'row'}}>{images}</View><View style={{flex:1, flexDirection: 'row', justifyContent: 'space-between'}}><Text style={{marginLeft: 10, marginBottom: 10,fontSize: 13, color: '#999999'}}>{rowData.Source}</Text><Text style={{marginRight:10,fontSize: 13, marginBottom: 10,color: '#999999'}}>{rowData.PublishTime}</Text></View><View style={{width, height:1, backgroundColor: '#EEEEEE'}}></View></TouchableOpacity>
)

我这里的 style 没有进行整理,所以看着比较乱,正式开发中应该整理到 styles 里,看起来就简洁多了。

现在运行就可以显示第一页的数据了。

项目结构

项目结构如下:

React Native :加载新闻列表

代码地址如下:
http://www.demodashi.com/demo/13212.html

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

React Native :加载新闻列表相关推荐

  1. React Native 加载多类型布局的实现——分类列表SectionList的封装

    目标:简化及规范SectionList的使用. 实现:基于SectionList的封装. 适用的情况       普通的线布局+列表/分类列表+普通线程布局+列表/分类列表.如下图: 如上图中1.2. ...

  2. React Native加载动画,lottie-web 将json解析成动画

    1.安装依赖 npm install lottie-web --save 2.建立resources文件夹,内部导入AE动画的json文件且新建Lottie.js文件,封装Component组件 Lo ...

  3. (仿头条APP项目)6.点击过的新闻列表文字变灰和下拉刷新与滚动加载新闻数据

    文章目录 一.点击过的新闻列表文字变灰 效果图 实现思路 导入ormlite数据库类依赖 利用ormlite创建数据库和表 创建数据库类MyDbHelper 创建数据库中的新闻实体类NewInfo 页 ...

  4. 《React Native 精解与实战》书籍连载「React Native 网络请求与列表绑定」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

  5. React 16 加载性能优化指南

    关于 React 应用加载的优化,其实网上类似的文章已经有太多太多了,随便一搜就是一堆,已经成为了一个老生常谈的问题. 但随着 React 16 和 Webpack 4.0 的发布,很多过去的优化手段 ...

  6. python保存大列表(list)数据到文件并后续重新加载为列表(list)对象实战

    python保存大列表(list)数据到文件并后续重新加载为列表(list)对象实战 笔者遇到的问题是这样的, 在做机器学习模型的时候,有的时候会使用相关性分析的方法来进行特征的筛选,去除冗余特征,降 ...

  7. OpenCV加载图像列表imagelist的实例(附完整代码)

    OpenCV加载图像列表imagelist的实例 OpenCV加载图像列表imagelist的实例 OpenCV加载图像列表imagelist的实例 #include "opencv2/im ...

  8. PHP+Ajax点击加载更多列表数据实例

    PHP+Ajax点击加载更多列表数据实例 一款简单实用的PHP+Ajax点击加载更多列表数据实例,实现原理:通过"更多"按钮向服务端发送Ajax请求,PHP根据分页参数查询将最新的 ...

  9. php ajax 加载列表,Ajax点击不断加载数据列表(图文教程)

    这篇文章主要介绍了Ajax点击不断加载数据列表的相关资料,需要的朋友可以参考下 Ajax简介 AJAX即"Asynchronous Javascript And XML"(异步Ja ...

最新文章

  1. 通信原理最佳接收-最佳接收准则
  2. J.U.C系列(二)CyclicBarrier的使用
  3. python安装与开发环境搭建实验总结_python实验一:python环境配置
  4. 预科教育计算机基础知识重点归纳,民族预科班计算机教育论文
  5. Spring-AnnotationConfigApplicationContext/ClassPathXmlApplicationContext
  6. 再谈PN学习(Tracking-Learning-Detection)
  7. C语言学生课程管理系统
  8. PS图层批量处理插件,支持Win、Mac系统
  9. stm32指纹考勤机 (程序源码包括app程序+pcb电路图+原件清单)
  10. 国资委定调联通电信前景:“共享竞合”的铁塔模式翻版
  11. 魅族的usb计算机连接无法使用,魅族16怎么连接电脑 魅族手机连接电脑无法识别...
  12. 全球最贵域名Sex.com将再度出售
  13. php授权微信自动扣款,【微信支付】微信代扣开发者文档
  14. vue 组件内引入外部在线js、css
  15. 数据库第一范式、第二范式、第三范式、BCNF范式
  16. WinCCV7.4sp1在win10
  17. 多线程(六)线程的五大生命周期,六个状态,七种基础状态
  18. waveform波形图(时域图)、spectrum(频谱图)、spectrogram(语谱图)、MFCC
  19. 摇摇棒C语言程序,AT89S52单片机16LED摇摇棒设计(含pcb文件,源程序等)
  20. 【已解决】linux开启端口 error: unrecognized arguments: -add-port=8080/tcp

热门文章

  1. linux sort多磁盘排序,linux shell sort多字段排序
  2. STM32F103:一.(2)STLINK的配置
  3. Windows核心编程条件变量
  4. pb 保存变量文件名_【Tensorflow 2.0 正式版教程】模型的保存、加载与迁移
  5. mysql 加减乘除取小数点_mysql加减乘除
  6. netlink 学习笔记 3.8.13内核
  7. (1)散列表(哈希表)的定义
  8. ajax传值给python_ajax向python脚本传递参数
  9. 二分法解决力扣374.猜数字大小 C语言
  10. [Alpha]Scrum Meeting#5