react-native-timeline-flatlist
v0.8.0
Published
Timeline component for React Native
Downloads
26,698
Maintainers
Readme
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
- Column Format (in v.0.2.0)
- Configuration
- 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
}}
/>
)
}