react-native-timeline-flatlist
react-native-timeline-flatlist copied to clipboard
FlatList based timeline component for React Native for iOS and Android
React Native Timeline Flatlist
Timeline component for React Native App work for Android and iOS
It's a fork of react-native-timeline-listview with some updates including FlatList, because old ListView is deprecated.
Examples in examples folder and on Expo https://expo.io/@eugnis/react-native-timeline-flatlist-examples
Table of Contents
- Installation
- Usage
- Basic usage
- Custom example
- Circle dot example
- Icon example
- Override render example
- Pull to refresh and load more example
- Column Format (in v.0.2.0)
- Single column right
- Two column
- Time container hiding
- Configuration
- Data Object
- Timeline
- Shift problem
Installation
npm i react-native-timeline-flatlist --save
or
yarn add react-native-timeline-flatlist
Basic Usage
import Timeline from 'react-native-timeline-flatlist'
constructor(){
super()
this.data = [
{time: '09:00', title: 'Event 1', description: 'Event 1 Description'},
{time: '10:45', title: 'Event 2', description: 'Event 2 Description'},
{time: '12:00', title: 'Event 3', description: 'Event 3 Description'},
{time: '14:00', title: 'Event 4', description: 'Event 4 Description'},
{time: '16:30', title: 'Event 5', description: 'Event 5 Description'}
]
}
render(){
return(
<Timeline
data={this.data}
/>
)
}
Custom
render(){
return(
<Timeline
//..other props
circleSize={20}
circleColor='rgb(45,156,219)'
lineColor='rgb(45,156,219)'
timeContainerStyle={{minWidth:52, marginTop: -5}}
timeStyle={{textAlign: 'center', backgroundColor:'#ff9797', color:'white', padding:5, borderRadius:13}}
descriptionStyle={{color:'gray'}}
options={{
style:{paddingTop:5}
}}
isUsingFlatlist={true}
/>
)
}
Circle Dot
render(){
return(
<Timeline
//..other props
innerCircle={'dot'}
/>
)
}
Icon
constructor(){
super()
this.data = [
{time: '09:00', title: 'Archery Training', description: 'The Beginner Archery and Beginner Crossbow course does not require you to bring any equipment, since everything you need will be provided for the course. ',lineColor:'#009688', icon: require('../img/archery.png')},
{time: '10:45', title: 'Play Badminton', description: 'Badminton is a racquet sport played using racquets to hit a shuttlecock across a net.', icon: require('../img/badminton.png')},
{time: '12:00', title: 'Lunch', icon: require('../img/lunch.png')},
{time: '14:00', title: 'Watch Soccer', description: 'Team sport played between two teams of eleven players with a spherical ball. ',lineColor:'#009688', icon: require('../img/soccer.png')},
{time: '16:30', title: 'Go to Fitness center', description: 'Look out for the Best Gym & Fitness Centers around me :)', icon: require('../img/dumbbell.png')}
]
}
render(){
return(
<Timeline
//..other props
innerCircle={'icon'}
/>
)
}
Also you can pass any React element as icon or iconDefault:
this.data = [
...
{time: '12:00', title: 'Custom rendered icon', icon: <Image
style={{width: 20, height: 20}}
source={{uri: 'https://reactnative.dev/img/tiny_logo.png'}}
/>},
...
]
}
Override Render
constructor(){
super()
this.renderDetail = this.renderDetail.bind(this)
this.data = [
{
time: '09:00',
title: 'Archery Training',
description: 'The Beginner Archery and Beginner Crossbow course does not require you to bring any equipment, since everything you need will be provided for the course. ',
lineColor:'#009688',
icon: require('../img/archery.png'),
imageUrl: 'https://cloud.githubusercontent.com/assets/21040043/24240340/c0f96b3a-0fe3-11e7-8964-fe66e4d9be7a.jpg'
},
{
time: '10:45',
title: 'Play Badminton',
description: 'Badminton is a racquet sport played using racquets to hit a shuttlecock across a net.',
icon: require('../img/badminton.png'),
imageUrl: 'https://cloud.githubusercontent.com/assets/21040043/24240405/0ba41234-0fe4-11e7-919b-c3f88ced349c.jpg'
},
{
time: '12:00',
title: 'Lunch',
icon: require('../img/lunch.png'),
},
{
time: '14:00',
title: 'Watch Soccer',
description: 'Team sport played between two teams of eleven players with a spherical ball. ',
lineColor:'#009688',
icon: require('../img/soccer.png'),
imageUrl: 'https://cloud.githubusercontent.com/assets/21040043/24240419/1f553dee-0fe4-11e7-8638-6025682232b1.jpg'
},
{
time: '16:30',
title: 'Go to Fitness center',
description: 'Look out for the Best Gym & Fitness Centers around me :)',
icon: require('../img/dumbbell.png'),
imageUrl: 'https://cloud.githubusercontent.com/assets/21040043/24240422/20d84f6c-0fe4-11e7-8f1d-9dbc594d0cfa.jpg'
}
]
}
renderDetail(rowData, sectionID, rowID) {
let title = <Text style={[styles.title]}>{rowData.title}</Text>
var desc = null
if(rowData.description && rowData.imageUrl)
desc = (
<View style={styles.descriptionContainer}>
<Image source={{uri: rowData.imageUrl}} style={styles.image}/>
<Text style={[styles.textDescription]}>{rowData.description}</Text>
</View>
)
return (
<View style={{flex:1}}>
{title}
{desc}
</View>
)
}
render(){
return(
<Timeline
//..other props
renderDetail={this.renderDetail}
/>
)
}
see full override render example
Pull to refresh and load more
onRefresh(){
//set initial data
}
onEndReached() {
//fetch next data
}
renderFooter() {
//show loading indicator
if (this.state.waiting) {
return <ActivityIndicator />;
} else {
return <Text>~</Text>;
}
}
render(){
return(
<Timeline
//..other props
options={{
refreshControl: (
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={this.onRefresh}
/>
),
renderFooter: this.renderFooter,
onEndReached: this.onEndReached
}}
/>
)
}
see full refresh and load more example
Column Format
Single Column Right
render(){
return(
<Timeline
//..other props
columnFormat='single-column-right'
/>
)
}
see full single column right example
Two Column
render(){
return(
<Timeline
//..other props
columnFormat='two-column'
/>
)
}
Time container hiding
render(){
return(
<Timeline
//..other props
showTime={false}
/>
)
}
Configuration
Data Object:
Property | Type | Default | Description |
---|---|---|---|
time | string | null | event time |
title | string | null | event title |
description | string or object | null | event description |
lineWidth | int | same as lineWidth of 'Timeline' | event line width |
lineColor | string | same as lineColor of 'Timeline' | event line color |
eventContainerStyle | object | null | custom styles of line |
circleSize | int | same as circleSize of 'Timeline' | event circle size |
circleColor | string | same as circleColor of 'Timeline' | event circle color |
dotColor | string | same as dotColor of 'Timeline' | event dot color (innerCircle = 'dot') |
icon | obj(image source) or React.Element | same as icon of 'Timeline' | event icon (innerCircle = 'icon' or 'element') |
position | string | null | event side in 'two-column' layout : 'left', 'right' |
Timeline:
Property | Type | Default | Description |
---|---|---|---|
data | data object | null | timeline data |
innerCircle | string | null | timeline mode : 'none', 'dot', 'icon', 'element' |
separator | bool | true | render separator line of events |
columnFormat | string | 'single-left' | can be 'single-column-left', 'single-column-right', 'two-column' |
lineWidth | int | 2 | timeline line width |
lineColor | string | '#007AFF' | timeline line color |
circleSize | int | 16 | timeline circle size |
circleColor | string | '#007AFF' | timeline circle color |
dotColor | string | 'white' | timeline dot color (innerCircle = 'dot') |
dotSize | int | circleSize / 2 | timeline dot size (innerCircle = 'dot') |
iconDefault (or icon) | obj(image source) or React.Element | same as icon of 'Timeline' | default event icon |
style | object | null | custom styles of Timeline container |
listViewStyle | object | null | custom styles of inner ListView |
listViewContainerStyle | object | null | custom styles of inner ListView container |
timeStyle | object | null | custom styles of event time |
titleStyle | object | null | custom styles of event title |
descriptionStyle | object | null | custom styles of event description |
iconStyle | object | null | custom styles of event icon |
separatorStyle | object | null | custom styles of separator |
rowContainerStyle | object | null | custom styles of event container |
eventContainerStyle | object | null | custom styles of the event part of the row (line) |
eventDetailStyle | object | null | custom styles of the event detail part of the row (line) |
timeContainerStyle | object | null | custom styles of container of event time |
detailContainerStyle | object | null | custom styles of container of event title and event description |
onEventPress | function(event) | null | function to be invoked when event was pressed |
renderTime | function(rowData, sectionID, rowID) | null | custom render event time |
renderDetail | function(rowData, sectionID, rowID) | null | custom render event title and event description |
renderCircle | function(rowData, sectionID, rowID) | null | custom render circle |
renderFullLine | bool | false | render event border on last timeline item |
options | object | null | ListView properties |
showTime | boolean | true | Time container options |
isUsingFlatlist | boolean | false | Render inner components in Flatlist (if false - render in View) |
Shift problem
Text width of event time may not be the same.
fix by add 'minWidth' in 'timeContainerStyle' to appropriate value
render(){
return(
<Timeline
//..other props
timeContainerStyle={{minWidth:72}}
/>
)
}
Timeline is rendered, but not displayed until scroll
fix by add removeClippedSubviews: false into options
render(){
return(
<Timeline
//..other props
options={{
removeClippedSubviews: false
}}
/>
)
}