This is a simple example of Sticky Headers in List Component of NativeBase made with Native ListView, NativeBase and Create React Native App tool. Detailed Setup instructions can be found below.
Note: Sticky Header support is currently unavailable for android in React Native ListView. It will soon be available, check out this issue.
Find Full Code here
![Sticky Header](https://docs.nativebase.io/docs/assets/StickyHeader.gif)
We aim to create a simple App that implements sticky headers as shown in the GIF above.
- Create React Native App: Use CRNA tool to create an App like this
$ npm install -g create-react-native-app
$ create-react-native-app my-app
$ cd my-app/
$ npm start
- NativeBase
npm install native-base@2 --save
- Configure dependencies
react-native link
Important: Additional steps are required to import fonts from native base. Refer to this
With all required Libraries installed, we can start with some real coding. In the root of your project create a folder src
. Inside this folder we create a file by the name of Application.js
.
Note: You might have some problems setting up the project due to version conflicts, make sure you use same versions as mentioned below in the package.json
By the end of all this your project structure and package.json
file should look something like this.
In your Application.js
inside src
folder add the following code.
Code src/Application.js
import React from 'react';
import Expo from 'expo';
import { ListView, View } from 'react-native';
import { List, ListItem, Container, Content, Header, Title, Body, Text } from 'native-base';
export default class Application extends React.Component {
constructor(){
super();
this.state= {
isReady: false,
dataSource : new ListView.DataSource({
rowHasChanged : (row1, row2) => row1 !== row2,
sectionHeaderHasChanged : (s1, s2) => s1 !== s2
})
};
}
populateList() {
this.setState({
dataSource : this.state.dataSource.cloneWithRowsAndSections([
["Movies","Prestige","Interstellar","Dark Knight", "Neighbours"],
["Music","Nirvana", "Imagine Dragons", "Avicii","Maya"],
["Places","Agra","Jamshedpur","Delhi", "Bangalore"],
["Things","Car","Table","Fan", "Chair"],
["People","Sankho","Aditya","Himanshu", "Kuldeep"],
["Roads","NH-11","MG Road","Brigade Road", "Nehru Road"],
["Buildings","Empire State","Burj Khalifa","Caspian", "Narnia"]
])
});
}
async componentWillMount() {
this.populateList();
await Expo.Font.loadAsync({
'Roboto': require('native-base/Fonts/Roboto.ttf'),
'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
});
this.setState({isReady: true});
}
renderSectionHeader(sectionData, sectionID) {
return (
<ListItem >
<Text>{sectionData[0]}</Text>
</ListItem>
);
}
renderRow(rowData, sectionID, rowID) {
console.log(rowID,rowData,sectionID, "renderRow");
if(rowID == 0){
console.log(rowData, "0 rowId");
return null;
}
return (
<ListItem>
<Text>{rowData}</Text>
</ListItem>
);
}
render() {
if (!this.state.isReady) {
return <Expo.AppLoading />;
}
return (
<Container>
<Header>
<Body>
<Title>Sticky Headers</Title>
</Body>
</Header>
<List
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderSectionHeader={this.renderSectionHeader}
/>
</Container>
);
}
}
Explained
- In our constructor, we initialize our state with a
dataSource
object. Use similar syntax to initialize theListView.dataSource
. async componentWillMount
function is used to load fonts for NativeBase as mentioned in previous examples. Check out this example.populateList
function creates our dataSource object to be used by our list.dataSource.cloneWithRowsAndSections
function will convert data into a ListView Map. Here we have used dummy data in a simple format, implementation can vary according data structure.- Next we simply place our
List
(wrapper around ListView) component from NativeBase and pass data as props as shown.
<List
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderSectionHeader={this.renderSectionHeader}
/>```
- In the <code>renderRow</code> prop we pass our defined function. <code>rowData, rowID and sectionID</code> are the available arguments with the function. <br /> We simple return a React component with respective data as shown. <br /> For <code>rowID == 0</code> we return null because it is the section header element. We do not want to display it as a list item.
- Similarly we implemented <code>renderSectionHeader</code> function, returning section headers, as shown above. <br />
## Wrapping Up
With our component made, we simply import the component in our <code>App.js</code> file and place it inside the render funtion. <br />
Build and run.