Focused cards in Flatlist React Native Typescript

 





import React, { useState } from 'react';

import { Dimensions, FlatList, StyleSheet, Text, View } from 'react-native';

interface InnerItem {
id: string;
title: string;
}

interface OuterItem {
id: string;
title: string;
innerData: InnerItem[];
}

const DATA: OuterItem[] = [
{
id: '1',
title: 'Outer Item 0',
innerData: [
{ id: '1a', title: 'Inner Item 1' },
{ id: '1b', title: 'Inner Item 2' },
{ id: '1c', title: 'Inner Item 3' },
{ id: '1d', title: 'Inner Item 4' },
{ id: '1e', title: 'Inner Item 5' },
{ id: '1f', title: 'Inner Item 6' },
{ id: '1g', title: 'Inner Item 7' },
{ id: '1h', title: 'Inner Item 8' },
],
},
{
id: '2',
title: 'Outer Item 1',
innerData: [
{ id: '2a', title: 'Inner Item 9' },
{ id: '2b', title: 'Inner Item 10' },
{ id: '2c', title: 'Inner Item 11' },
{ id: '2d', title: 'Inner Item 12' },
{ id: '2e', title: 'Inner Item 13' },
{ id: '2f', title: 'Inner Item 14' },
{ id: '2g', title: 'Inner Item 15' },
],
},
{
id: '3',
title: 'Outer Item 2',
innerData: [
{ id: '3a', title: 'Inner Item 9' },
{ id: '3b', title: 'Inner Item 10' },
{ id: '3c', title: 'Inner Item 11' },
{ id: '3d', title: 'Inner Item 12' },
{ id: '3e', title: 'Inner Item 13' },
],
},
{
id: '4',
title: 'Outer Item 3',
innerData: [
{ id: '4a', title: 'Inner Item 9' },
{ id: '4b', title: 'Inner Item 10' },
{ id: '4c', title: 'Inner Item 11' },
{ id: '4d', title: 'Inner Item 12' },
{ id: '4e', title: 'Inner Item 13' },
{ id: '4f', title: 'Inner Item 14' },
{ id: '4g', title: 'Inner Item 15' },
],
},
{
id: '5',
title: 'Outer Item 4',
innerData: [
{ id: '5a', title: 'Inner Item 9' },
{ id: '5b', title: 'Inner Item 10' },
{ id: '5c', title: 'Inner Item 11' },
{ id: '5d', title: 'Inner Item 12' },
{ id: '5e', title: 'Inner Item 13' },
{ id: '5f', title: 'Inner Item 14' },
{ id: '5g', title: 'Inner Item 15' },
],
},
];

const InnerItem = ({ title }: { title: string }) => (
<View style={styles.innerItem}>
<Text>{title}</Text>
</View>
);

const OuterItem = ({ title, innerData, focused }: { title: string; innerData: InnerItem[], focused: boolean }) => {
const renderInnerItem = ({ item }: { item: InnerItem }) => <InnerItem title={item.title} />;

return (
<View style={[styles.outerItem, {backgroundColor: focused ? 'green' : undefined}]}>
<Text style={styles.outerItemTitle}>{title}</Text>
<FlatList
data={innerData}
renderItem={renderInnerItem}
keyExtractor={(item) => item.id}
horizontal={true}
showsVerticalScrollIndicator={false}
/>
</View>
);
};

const ListScreen = () => {
const [focusedItemsId, setFocusedItemsId] = useState<string[] | null>(null);
const [focusedItemsIndex, setFocusedItemsIndex] = useState<number[] | null>(null);
const [itemLayouts, setItemLayouts] = useState([]);
const windowsHeight = Dimensions.get('window').height;
const handleItemLayout = (index, event) => {
const { height } = event.nativeEvent.layout;
console.log('height FROM iTEMLAYOUT|============>', JSON.stringify(height));
setItemLayouts(prevLayouts => {
const newLayouts = [...prevLayouts];
newLayouts[index] = height;
return newLayouts;
});
};

const renderItem = ({ item, index }: { item: OuterItem, index: number }) => (
<View onLayout={(event) => handleItemLayout(index, event)}>
<OuterItem title={item.title} innerData={item.innerData} focused={focusedItemsIndex.includes(index)}/>
</View>
);

const handleScroll = (event: { nativeEvent: { contentOffset: { y: number } } }) => {
const y = event.nativeEvent.contentOffset.y;
const scrolledFocusedPoints = {
bottomPoint: y + windowsHeight * 0,
centerPoint: y + windowsHeight / 2 ,
topPoint: y + windowsHeight ,
}

let itemPositionTop = 0;
let itemPositionBottom = 0;
let focusedIndexes: number[] = []


DATA.forEach((_item, index) => {
const itemHeight = itemLayouts[index]
itemPositionTop += itemHeight;
if (itemPositionTop <= scrolledFocusedPoints.topPoint && itemPositionBottom >= scrolledFocusedPoints.bottomPoint){
focusedIndexes.push(index)
}
itemPositionBottom += itemHeight
})

// const newFocusedItemId = DATA[index]?.id || null;

setFocusedItemsIndex(focusedIndexes)
console.log('focusedIndexes |============>', JSON.stringify(focusedIndexes));
};

return (
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
showsVerticalScrollIndicator={false}
viewabilityConfig={{
itemVisiblePercentThreshold: 50,
}}
onScroll={handleScroll}
scrollEventThrottle={16}
/>
);
};

const styles = StyleSheet.create({
outerItem: {
backgroundColor: '#be3030',
paddingVertical: 10,
paddingHorizontal: 15,
marginBottom: 10,
},
outerItemTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 10,
},
innerItem: {
backgroundColor: '#1004fb',
padding: 10,
marginVertical: 5,
marginHorizontal: 10,
height: 300,
width: 240
},
});

export default ListScreen;

Comments

Popular posts from this blog

Android/Java: Crear un SplashScreen para nuestra aplicaciĆ³n

Android/Java: Video de fondo en nuestro Login

Solve SecurityError: localStorage is not available for opaque origins React Native