[RN] React Native 好用的时间线 组件
React Native 好用的时间线 组件
效果如下:

实现方法:
一、组件封装
CustomTimeLine.js
"use strict";
import React, {Component} from "react";
import {
StyleSheet,
ListView,
Image,
View,
Text,
TouchableOpacity
} from "react-native";
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
sectionHeaderHasChanged: (s1, s2) => s1 !== s2
});
const defaultCircleSize = ;
const defaultCircleColor = "#007AFF";
const defaultLineWidth = ;
const defaultLineColor = "#007AFF";
const defaultTimeTextColor = "black";
const defaultDotColor = "white";
const defaultInnerCircle = "none";
export default class CustomTimeLine extends Component {
static defaultProps = {
circleSize: defaultCircleSize,
circleColor: defaultCircleColor,
lineWidth: defaultLineWidth,
lineColor: defaultLineColor,
innerCircle: defaultInnerCircle,
columnFormat: "single-column-left",
separator: false,
showTime: true
};
constructor(props, context) {
super(props, context);
this._renderRow = this._renderRow.bind(this);
this.renderTime = (this.props.renderTime
? this.props.renderTime
: this._renderTime
).bind(this);
this.renderDetail = (this.props.renderDetail
? this.props.renderDetail
: this._renderDetail
).bind(this);
this.renderCircle = (this.props.renderCircle
? this.props.renderCircle
: this._renderCircle
).bind(this);
this.renderEvent = this._renderEvent.bind(this);
this.state = {
data: this.props.data,
dataSource: ds.cloneWithRows(this.props.data),
x: ,
width:
};
}
componentWillReceiveProps(nextProps) {
this.setState({
data: nextProps.data,
dataSource: ds.cloneWithRows(nextProps.data)
});
}
render() {
return (
<View style={[styles.container, this.props.style]}>
<ListView
ref="listView"
style={[styles.listview, this.props.listViewStyle]}
dataSource={this.state.dataSource}
renderRow={this._renderRow}
automaticallyAdjustContentInsets={false}
{...this.props.options}
/>
</View>
);
}
_renderRow(rowData, sectionID, rowID) {
let content = null;
switch (this.props.columnFormat) {
case "single-column-left":
content = (
<View style={[styles.rowContainer, this.props.rowContainerStyle]}>
{this.renderTime(rowData, sectionID, rowID)}
{this.renderEvent(rowData, sectionID, rowID)}
{this.renderCircle(rowData, sectionID, rowID)}
</View>
);
break;
case "single-column-right":
content = (
<View style={[styles.rowContainer, this.props.rowContainerStyle]}>
{this.renderEvent(rowData, sectionID, rowID)}
{this.renderTime(rowData, sectionID, rowID)}
{this.renderCircle(rowData, sectionID, rowID)}
</View>
);
break;
case "two-column":
content =
rowID % === ? (
<View style={[styles.rowContainer, this.props.rowContainerStyle]}>
{this.renderTime(rowData, sectionID, rowID)}
{this.renderEvent(rowData, sectionID, rowID)}
{this.renderCircle(rowData, sectionID, rowID)}
</View>
) : (
<View style={[styles.rowContainer, this.props.rowContainerStyle]}>
{this.renderEvent(rowData, sectionID, rowID)}
{this.renderTime(rowData, sectionID, rowID)}
{this.renderCircle(rowData, sectionID, rowID)}
</View>
);
break;
}
return <View key={rowID}>{content}</View>;
}
_renderTime(rowData, sectionID, rowID) {
if (!this.props.showTime) {
return null;
}
var timeWrapper = null;
switch (this.props.columnFormat) {
case "single-column-left":
timeWrapper = {
alignItems: "flex-end"
};
break;
case "single-column-right":
timeWrapper = {
alignItems: "flex-start"
};
break;
case "two-column":
timeWrapper = {
flex: ,
alignItems: rowID % === ? "flex-end" : "flex-start"
};
break;
}
return (
<View style={timeWrapper}>
<View style={[styles.timeContainer, this.props.timeContainerStyle]}>
<Text style={[styles.time, this.props.timeStyle]}>
{rowData.time}
</Text>
</View>
</View>
);
}
_renderEvent(rowData, sectionID, rowID) {
const lineWidth = rowData.lineWidth
? rowData.lineWidth
: this.props.lineWidth;
const isLast = this.props.renderFullLine
? !this.props.renderFullLine
: this.state.data.slice(-)[] === rowData;
const lineColor = isLast
? "rgba(0,0,0,0)"
: rowData.lineColor ? rowData.lineColor : this.props.lineColor;
let opStyle = null;
switch (this.props.columnFormat) {
case "single-column-left":
opStyle = {
borderColor: lineColor,
borderLeftWidth: lineWidth,
borderRightWidth: ,
marginLeft: ,
paddingLeft:
};
break;
case "single-column-right":
opStyle = {
borderColor: lineColor,
borderLeftWidth: ,
borderRightWidth: lineWidth,
marginRight: ,
paddingRight:
};
break;
case "two-column":
opStyle =
rowID % ==
? {
borderColor: lineColor,
borderLeftWidth: lineWidth,
borderRightWidth: ,
marginLeft: ,
paddingLeft:
}
: {
borderColor: lineColor,
borderLeftWidth: ,
borderRightWidth: lineWidth,
marginRight: ,
paddingRight:
};
break;
}
return (
<View
style={[styles.details, opStyle]}
onLayout={evt => {
if (!this.state.x && !this.state.width) {
const {x, width} = evt.nativeEvent.layout;
this.setState({x, width});
}
}}
>
<TouchableOpacity
disabled={this.props.onEventPress == null}
style={[this.props.detailContainerStyle]}
onPress={() =>
this.props.onEventPress ? this.props.onEventPress(rowData) : null
}
>
<View style={styles.detail}>
{this.renderDetail(rowData, sectionID, rowID)}
</View>
{this._renderSeparator()}
</TouchableOpacity>
</View>
);
}
_renderDetail(rowData, sectionID, rowID) {
let title = rowData.description ? (
<View>
<Text style={[styles.title, this.props.titleStyle]}>
{rowData.title}
</Text>
<Text style={[styles.description, this.props.descriptionStyle]}>
{rowData.description}
</Text>
</View>
) : (
<Text style={[styles.title, this.props.titleStyle]}>{rowData.title}</Text>
);
return <View style={styles.container}>{title}</View>;
}
_renderCircle(rowData, sectionID, rowID) {
var circleSize = rowData.circleSize
? rowData.circleSize
: this.props.circleSize ? this.props.circleSize : defaultCircleSize;
var circleColor = rowData.circleColor
? rowData.circleColor
: this.props.circleColor ? this.props.circleColor : defaultCircleColor;
var lineWidth = rowData.lineWidth
? rowData.lineWidth
: this.props.lineWidth ? this.props.lineWidth : defaultLineWidth;
var circleStyle = null;
switch (this.props.columnFormat) {
case "single-column-left":
circleStyle = {
width: this.state.x ? circleSize : ,
height: this.state.x ? circleSize : ,
borderRadius: circleSize / ,
backgroundColor: circleColor,
left: this.state.x - circleSize / + (lineWidth - ) /
};
break;
case "single-column-right":
circleStyle = {
width: this.state.width ? circleSize : ,
height: this.state.width ? circleSize : ,
borderRadius: circleSize / ,
backgroundColor: circleColor,
left: this.state.width - circleSize / - (lineWidth - ) /
};
break;
case "two-column":
circleStyle = {
width: this.state.width ? circleSize : ,
height: this.state.width ? circleSize : ,
borderRadius: circleSize / ,
backgroundColor: circleColor,
left: this.state.width - circleSize / - (lineWidth - ) /
};
break;
}
var innerCircle = null;
switch (this.props.innerCircle) {
case "icon":
let iconSource = rowData.icon ? rowData.icon : this.props.icon;
let iconStyle = {
height: circleSize,
width: circleSize
};
innerCircle = (
<Image
source={iconSource}
style={[iconStyle, this.props.iconStyle]}
/>
);
break;
case "dot":
let dotStyle = {
height: circleSize / ,
width: circleSize / ,
borderRadius: circleSize / ,
backgroundColor: rowData.dotColor
? rowData.dotColor
: this.props.dotColor ? this.props.dotColor : defaultDotColor
};
innerCircle = <View style={[styles.dot, dotStyle]}/>;
break;
}
return (
<View style={[styles.circle, circleStyle, this.props.circleStyle]}>
{innerCircle}
</View>
);
}
_renderSeparator() {
if (!this.props.separator) {
return null;
}
return <View style={[styles.separator, this.props.separatorStyle]}/>;
}
}
const styles = StyleSheet.create({
container: {
flex:
},
listview: {
flex:
},
sectionHeader: {
marginBottom: ,
backgroundColor: "#007AFF",
height: ,
justifyContent: "center"
},
sectionHeaderText: {
color: "#FFF",
fontSize: ,
alignSelf: "center"
},
rowContainer: {
flexDirection: "row",
flex: ,
//alignItems: 'stretch',
justifyContent: "center"
},
timeContainer: {
minWidth:
},
time: {
textAlign: "right",
color: defaultTimeTextColor
},
circle: {
width: ,
height: ,
borderRadius: ,
position: "absolute",
left: -,
alignItems: "center",
justifyContent: "center"
},
dot: {
width: ,
height: ,
borderRadius: ,
backgroundColor: defaultDotColor
},
title: {
fontSize: ,
fontWeight: "bold"
},
details: {
borderLeftWidth: defaultLineWidth,
flexDirection: "column",
flex:
},
detail: {paddingTop: , paddingBottom: },
description: {
marginTop:
},
separator: {
height: ,
backgroundColor: "#aaa",
marginTop: ,
marginBottom:
}
});
代码调用:
import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native';
import Timeline from './CustomTimeLine';
export default class TestTimeLine extends Component {
constructor() {
super()
this.data = [
{time: '09:00', title: '商家已接单', description: 'Event 1 Description'},
{time: '10:45', title: '正在沟通', description: 'Event 2 Description'},
{time: '12:00', title: '合同签订', description: 'Event 3 Description'},
{time: '14:00', title: '订单完成', description: 'Event 4 Description'},
{time: '16:30', title: '用户评价', description: 'Event 5 Description'}
]
}
render() {
return (
<View style={styles.container}>
<Timeline
style={styles.list}
data={this.data}
showTime={true}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: ,
padding: ,
paddingTop: ,
backgroundColor: 'white'
},
list: {
flex: ,
marginTop: ,
},
});
更多使用方法,参考:
https://github.com/thegamenicorus/react-native-timeline-listview
本博客地址: wukong1688
本文原文地址:https://www.cnblogs.com/wukong1688/p/11049014.html
转载请著名出处!谢谢~~
[RN] React Native 好用的时间线 组件的更多相关文章
- [RN] React Native 幻灯片效果 Banner
[RN] React Native 幻灯片效果 Banner 1.定义Banner import React, {Component} from 'react'; import {Image, Scr ...
- [RN] React Native 实现图片预览
[RN] React Native 实现图片预览 效果预览: 代码如下: 'use strict'; import React, {Component} from 'react'; import {I ...
- [RN] React Native 常见基本问题归纳总结
[RN] React Native 常见基本问题归纳总结 本问题总结涉及到版本为: "react": "16.8.3","react-native& ...
- [RN] React Native 关闭所有黄色警告
[RN] React Native 关闭所有黄色警告 console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please u ...
- [RN] React Native 下实现底部标签(支持滑动切换)
上一篇文章 [RN] React Native 下实现底部标签(不支持滑动切换) 总结了不支持滑动切换的方法,此篇文章总结出 支持滑动 的方法 准备工作之类的,跟上文类似,大家可点击上文查看相关内容. ...
- [RN] React Native 常用命令行
[RN] React Native 常用命令行 1.查看当前版本 react-native --version 或 react-native -v 2.创建指定版本的React Native项目 1) ...
- [RN] React Native 实现 类似QQ 登陆页面
[RN] React Native 实现 类似QQ 登陆页面 一.主页index.js 项目目录下index.js /** * @format */ import {AppRegistry} from ...
- 基于React Native的Material Design风格的组件库 MRN
基于React Native的Material Design风格的组件库.(为了平台统一体验,目前只打算支持安卓) 官方网站 http://mrn.js.org/ Github https://git ...
- [RN] React Native 打包时 减少 Apk 的大小
React Native 打包时 减少 Apk 的大小 主要有两个方法: 在打包前设置 android\app\build.gradle 文件中 1) def enableProguardInRele ...
随机推荐
- spring bean的三种管理方式·
1.无参构造函数 1.xml文件配置内容 <!--无参构造函数--> <bean id="bean1" class="com.imooc.ioc.dem ...
- Python - 批量下载 IIS 共享的文件
1.说明 用 IIS 以WEB形式发布了本地文件夹,提供文件下载,并设置了访问权限:默认下载需要点击一个一个的下载,web界面如下: 3.脚本 执行脚本批量下载文件,会在当前目录创建文件夹,并压缩该文 ...
- axios的各种传参方式
axios的各种传参方式 1. params方式 axios({ url: '/users', method: 'get', params: { id: '11111', name: '22222' ...
- 使用JavaScript几种简单的排序
前几天在工作碰到一个json对象排序的问题,一直认为JavaScript不能进行对象的排序,其实并不是,今天就来总结下常见的几种简单排序: 第一类 纯数字: var arrOld = [4,10,9, ...
- UVA 10924 Prime Words 题解
Prime Words A prime number is a number that has only two divisors: itself and the number one. Exampl ...
- Can't locate Math/Round.pm in @INC
遭遇报错: Can't locate Math/Round.pm in @INC 经过亲自测试,下面的命令解决了我的问题. yum install perl-Math-Round 参考资料 ===== ...
- Hbase Filter之PrefixFilter
PrefixFilter PrefixFilter是将rowkey前缀为指定字符串的数据全部过滤出来并返回给用户.例如: Scan scan = new Scan(); scan.setFilter( ...
- TF-IDF & CNN
TF-IDF----------------------------------------------------------------认为一个单词出现的文本频率越小,它区别不同类别的能力就越大, ...
- everything 13问
[1]everything 由来? everything 是澳大利亚人David Carpenter开发的一个运行于windows系统,基于文件.文件夹名称的快速免费搜索引擎. 自从问世以来,因其占用 ...
- STM32 串口通信基础知识
1.串口通信简介 通信接口的两种方式: 并行通信 -传输原理:数据各个位同时传输. -优点:速度快 -缺点:占用引脚资源多 串行通信 -传输原理:数据按位顺序传输. -优点:占用引脚资源少 -缺点:速 ...