I'm using multi-column FlatList
in my React Native application to display items like below (left image). I'm trying to integrate AdMob banner into the application like many other apps did, and insert the ads banner in the middle of the list, like below (right image).
As far as I can tell, FlatList doesn't support this type of layout out-of-the-box. I'm wondering what would be a good practice to implement this feature and doesn't impact app performance.
(Side note, the list supports pull-to-refresh and infinite loading when approaching end of the list.).
Thank you in advance for any suggestions.
In such a case, I always recommend to drop the numColumns
property and replace it by a custom render function, which handles the columns by its own.
Let's say we have the following data structure:
const DATA =
[{ id: 1, title: "Item One"}, { id: 2, title: "Item Two"}, { id: 3, title: "Item Three"},
{ id: 4, title: "Item Four"}, { id: 5, title: "Item Five"}, { id: 6, title: "Item Six"},
{ id: 7, title: "Item Seven"}, { id:8, title: "Item Eight"}, { id: 9, title: "Item Nine"},
{ id: 10, title: "Item Ten"}, { id: 11, title: "Item eleven"},
{ id: 12, title: "Item Twelve"}, { id: 13, title: "Item Thirteen"}];
As I said we don't use the numColumns property instead we are restructuring our data so we can render our list how we want. In this case we want to have 3 columns and after six items we want to show an ad banner.
Data Modification:
modifyData(data) {
const numColumns = 3;
const addBannerAfterIndex = 6;
const arr = [];
var tmp = [];
data.forEach((val, index) => {
if (index % numColumns == 0 && index != 0){
arr.push(tmp);
tmp = [];
}
if (index % addBannerAfterIndex == 0 && index != 0){
arr.push([{type: 'banner'}]);
tmp = [];
}
tmp.push(val);
});
arr.push(tmp);
return arr;
}
Now we can render our transformed data:
Main render function:
render() {
const newData = this.modifyData(DATA); // here we can modify the data, this is probably not the spot where you want to trigger the modification
return (
<View style={styles.container}>
<FlatList
data={newData}
renderItem={({item, index})=> this.renderItem(item, index)}
/>
</View>
);
}
RenderItem Function:
I removed some inline styling to make it more clearer.
renderItem(item, index) {
// if we have a banner item we can render it here
if (item[0].type == "banner"){
return (
<View key={index} style={{width: WIDTH-20, flexDirection: 'row'}}>
<Text style={{textAlign: 'center', color: 'white'}}> YOUR AD BANNER COMPONENT CAN BE PLACED HERE HERE </Text>
</View>
)
}
//otherwise we map over our items and render them side by side
const columns = item.map((val, idx) => {
return (
<View style={{width: WIDTH/3-20, justifyContent: 'center', backgroundColor: 'gray', height: 60, marginLeft: 10, marginRight: 10}} key={idx}>
<Text style={{textAlign: 'center'}}> {val.title} </Text>
</View>
)
});
return (
<View key={index} style={{width: WIDTH, flexDirection: 'row', marginBottom: 10}}>
{columns}
</View>
)
}
Output:
Working Example:
https://snack.expo.io/SkmTqWrJS
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With