'Vertical scrolling where attribute name row is fixed and horizontal scrolling where left most column is fixed in React Native
So far I've achieved this:

//code on data listing screen with a vertical flatlist
const DataListing = props => {
const memoizedValue = useMemo(() => renderItem, [props.coinData]);
const renderItem = ({item}) => {
return (
<View
style={{
flexDirection: 'row',
backgroundColor: item?.id % 2 ? '#ffffff' : '#f9f9f9f9',
height: 40,
alignItems: 'center',
}}>
{/* coin */}
{item.coin ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.coin}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* open time */}
{item.openTime ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.openTime}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* open */}
{item.open ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.open}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* high */}
{item.high ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.high}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* low */}
{item.low ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.low}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* close */}
{item.close ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.close}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* quote asset volume */}
{item.quoteAssetVolume ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.quoteAssetVolume}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* trade number */}
{item.tradeNumber ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.tradeNumber}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* tracker buy base */}
{item.takerBuyBase ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.takerBuyBase}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* tracker buy quote */}
{item.takerBuyQuote ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.takerBuyQuote}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* price change */}
{item.priceChange ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.priceChange}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* price change % */}
{item.priceChangePercent ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.priceChangePercent}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* previos close price */}
{item.prevClosePrice ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.prevClosePrice}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* last price */}
{item.lastPrice ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.lastPrice}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* open price */}
{item.openPrice ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.openPrice}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* low price */}
{item.lowPrice ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.lowPrice}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* price volume */}
{item.pricevolume ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.pricevolume}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* quote volume */}
{item.quoteVolume ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.quoteVolume}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* price open time */}
{item.priceopenTime ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.priceopenTime}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* price close time */}
{item.pricecloseTime ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.pricecloseTime}
</Text>
) : (
<View style={{width: 150}} />
)}
{/* created at */}
{item.created_at ? (
<Text style={{width: 150, textAlign: 'center', color: '#000000'}}>
{item.created_at}
</Text>
) : (
<View style={{width: 150}} />
)}
</View>
);
};
return (
<FlatList
showsVerticalScrollIndicator={false}
data={props.coinData}
keyExtractor={(item, index) => index}
renderItem={renderItem}
/>
);
};
export default DataListing;
// code on data attributes page
const DataAttributes = props => {
return (
// container
<View style={{flexDirection: 'row'}}>
{/* coin name */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
COIN
</Text>
</TouchableOpacity>
{/* open time */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
OPEN TIME
</Text>
</TouchableOpacity>
{/* open */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
OPEN
</Text>
</TouchableOpacity>
{/* high */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
HIGH
</Text>
</TouchableOpacity>
{/* low */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
LOW
</Text>
</TouchableOpacity>
{/* close */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
CLOSE
</Text>
</TouchableOpacity>
{/* quote asset volume */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
VOLUME
</Text>
</TouchableOpacity>
{/* trade number */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
TRADE NUMBER
</Text>
</TouchableOpacity>
{/* taker buy base */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
TAKER BUY BASE
</Text>
</TouchableOpacity>
{/* taker buy quote */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
TAKER BUY QUOTE
</Text>
</TouchableOpacity>
{/* price change */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
PRICE CHANGE
</Text>
</TouchableOpacity>
{/* price change percent */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
PRICE CHANGE %
</Text>
</TouchableOpacity>
{/* previos close price */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
PREVIOUS CLOSE PRICE
</Text>
</TouchableOpacity>
{/* last price */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
LAST PRICE
</Text>
</TouchableOpacity>
{/* open price */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
OPEN PRICE
</Text>
</TouchableOpacity>
{/* low price */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
LOW PRICE
</Text>
</TouchableOpacity>
{/* price volume */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
PRICE VOLUME
</Text>
</TouchableOpacity>
{/* quote volume */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
QUOTE VOLUME
</Text>
</TouchableOpacity>
{/* price open time */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
PRICE OPEN TIME
</Text>
</TouchableOpacity>
{/* price close time */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRightWidth: 1,
borderColor: '#31313199',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
PRICE CLOSE TIME
</Text>
</TouchableOpacity>
{/* created at */}
<TouchableOpacity
style={{
flexDirection: 'row',
backgroundColor: '#FDE047',
height: 40,
width: 150,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => {}}>
<Text
style={{
fontSize: 10,
fontWeight: '400',
color: '#000000',
}}>
CREATED AT
</Text>
</TouchableOpacity>
</View>
);
};
export default DataAttributes;
// then they are imported to home and put inside a horizontal scrollview
import DataAttributes from '../Components/HomeScreen/DataAttributes';
import DataListing from '../Components/HomeScreen/DataListing';
const HomeScreen = ({navigation}) => {
const [coinData, setCoinData] = useState([]);
useEffect(() => {
coinStastics();
}, []);
// fetching coin statistics
const coinStastics = async () => {
const header = {
'Content-Type': 'application/json',
};
await axios
.post(baseUrl + coin_statistics, '', {headers: header})
.then(res => {
setCoinData(res.data.data);
})
.catch(function (error) {
// handle error
console.log(error);
});
};
return (
<SafeAreaView
style={{
flex: 1,
alignItems: 'center',
}}>
<Header/>
{/* DATA */}
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View>
{/* attributes for data */}
<DataAttributes coinData={coinData} setCoinData={setCoinData} />
{/* data section */}
<DataListing coinData={coinData} />
</View>
</ScrollView>
<Footer />
</>
)}
</SafeAreaView>
);
};
export default HomeScreen;
I am expecting something like this, where I can scroll the data portion vertically where the the column names / attribute names stay fixed but as soon I start scrolling horizontally all the columns should start to respond except the left most one, it should stay fixed along with it's COLUMN NAME on top

Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
