How To Get Springy/Bouncy Effect When Scrolling In Flatlist - reactjs

How can I make a vertical Flatlist item in React Native to snap into position on scroll and fill up the current window? I want each item to fill up the screen and not for the previous or coming items to show. An example of the effect I want is the achieved in ScrollView by having pagingEnabled={true}. But my problem with this, when applied to Flatlist, is that parts of the previous item shows at the top of subsequent views. This increases in size as you scroll down. The effect I want is like if you are scrolling through TikTok. You see how each video fills up the screen and when you scroll up or down, there is a springy effect that if the scroll is not complete, the current video bounces back into position.
This is my current flatlist:
<FlatList
data={DATA}
renderItem={renderItems}
keyExtractor={item => item.id}
Animated={true}
removeClippedSubviews={true}
refreshControl={
< RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
/>}
Please note that I am using Functional components not classes.
Thanks in advance.

Wow! After hours on this, GeekForGeeks has delivered me!
This is the article and all thanks to Brijen Makwana.
The answer is in applying three props already provided by Flatlist to your/my flatlist. They are:
snapToAlignment='start'
decelerationRate={'fast'}
snapToInterval={windowHeight}
So my Flatlist will now look like this:
<FlatList
data={DATA}
renderItem={renderItems}
keyExtractor={item => item.id}
snapToAlignment='start'
decelerationRate={'fast'}
snapToInterval={windowHeight}
/>
Remember to first Import Dimensions from React native and make the Item View have the full height and full width of the window (that is the screen):
import { StyleSheet, View, FlatList, Dimensions } from "react-native";
const windowHeight = Dimensions.get('window').height;
const windowWidth = Dimensions.get('window').width;
In your stylesheet:
StyleOfItemsContainerForFlatList: {
height: windowHeight,
width: windowWidth,
justifyContent: "center",
alignItems: "center"
},
I removed the Refreshcontrol here since it is not relevant to this answer.
And just like that my React Native Vertical Flatlist now has a bouncy, springy transition animation like Tiktok and Instagram!
And also, the article shows how you can apply snap animation on Horizontal Flatlists also.
Please check the original article for details.

Related

React Native FlatList: how to reset scroll position

I have a horizontal FlatList in my React Native iOS app. At the bottom of the screen, the FlatList is displayed with 5 items. If you click on the last item (scrolled all the way to the right), the screen will refresh and the FlatList will remain scrolled to the right. How can I get the FlatList to always reset the scroll position (to scroll from the beginning) when the screen changes?
Edit: I have a feeling that my screen is not actually "refreshing" but rather merely changing the data shown on the screen. In this case I may need to trigger a refresh of the screen somehow to cause the FlatList to reset the scroll position? Any help would be greatly appreciated!
const HorizontalScroll = ({items, handlePress}) => {
const renderItem = ({item}) => {
const itemData = { color: item.color, title: item.title };
return <HorizontalItem itemData={itemData} handlePress={handlePress} />;
};
return (
<View style={styles.container}>
<FlatList
data={items}
renderItem={renderItem}
horizontal={true}
numColumns={1}
key={(item) => item.id}
initialNumToRender={5}
scrollToIndex={0}
ItemSeparatorComponent={() => <View style={{width: 8}} />}>
</FlatList>
</View>
);
};
I solved this problem by forcing a refresh of the component. Specifically, I added a key prop to my component so that every time the key value changes, it remounts the component. This causes the FlatList to reset the scroll position to the beginning.
<View key={items[0].title}>
{content}
</View>

How to fix React Native ScrollView default at bottom

I'm trying to build a Chat App with React Native.
In the chat screen, there is a ScrollView for every message sent and received.
However, every time when I leave the screen and back in, the default of the ScrollView is at the top. I've written a function to scrollToEnd after rendered, but that is After Rendered, I need to set the ScrollView at the bottom before it actually shows.
I've tried (but users can see it scrolling as soon as it is rendered):
const scrollToBottom = () => {
scrollEl.current.scrollIntoView({ behavior: 'smooth'})
}
useEffect(() => {
scrollToBottom()
}, [scrollEl, loading, chatHistory])
return(
<ScrollView bottom={0} w="100%" bg="blueGray.100" inverted>
<VStack flex={1} w="100%" id="VStack">
{!loading && chatHistory.chats[roomId] && chatHistory.chats[roomId].length > 0 && chatHistory.chats[roomId].map((chat, index) =>
<ChatItem type={chat.type}
text={chat.text}
fromSelf={chat.fromSelf}
key={index}
/>
)}
<Box ref={scrollEl} />
</VStack>
</ScrollView>
)
I've tried:
Set scale: -1 at CSS, which actually invert the whole screen upside down.
Thus, I have to invert every single message to invert them back to the normal side.
Meanwhile, the scrolling is totally in the opposite way when you scroll by mouse or slide on the screen.
Any solutions or suggestions?
Thanks!
I hardly recommend you to use FlatList cause of the performance of the rendering list
https://reactnative.dev/docs/flatlist
Also in FlatList you can achieve what exactly you want
https://reactnative.dev/docs/flatlist#initialscrollindex
Even if you want better performance below library handle list better than FlatList
https://github.com/Flipkart/recyclerlistview

Prevent Flatlist to scroll to top on content size changes

Inside a FlatList I have accordions (by react-native-paper). When I scroll to any position and open/close an accordion, The FlatList scrolls to the top of the screen. How should I prevent it?
in another word when an accordion gets expanded, the content size is changed. How to stay where the user was on content size changes. The current snippet does not work and the stored y position resets.
const flatListRef = React.useRef<FlatList<any>>(null);
const yOffset = React.useRef<number>(0);
<FlatList
ref={flatListRef}
data={properties}
renderItem={renderItem}
keyExtractor={(item) => `${item.id}`}
onContentSizeChange={() =>{flatListRef.current!.scrollToOffset({offset: yOffset.current, animated: false});}}
onEndReached={onEndReached}
onEndReachedThreshold={0}
scrollEventThrottle={15}
onScroll={(e) => {yOffset.current = e.nativeEvent.contentOffset.y;}}
ListFooterComponent={<ActivityIndicator animating={loading} size="small" />}
/>
for instance, (inside onContentSizeChange conosle.log(yOffset.current)) if I scroll to yOffset 850 and exapnd the accordion there, in console I see two logs, 850, then 126 (which 126 returns to the top) which indicates, onScroll was called and yOffset changed.
Not sure about your question here, but if you don't want to scroll to top on accordion expansion, just remove onContentSizeChange and onScroll prop.
Also, if you want that on accordion press that should come on top of the screen just wrap the Accordion in a View and get the expanded height/xy coordinates of the View using the onLayout prop and then you can use the Flatlist's scrollToOffset() to scroll to that particular Accordion

What is the correct way to position the main content around appbars and drawers in material-ui?

I use material-ui for a lot of React apps. I'm using the responsive drawer + the appbar for a project and I'm confused about how best to position content around these navs. Do you just take your main content and put big top and left margins? Is there a better way to do this sort of thing ?
On my grid now, I have:
const styles = theme => ({
root: {
padding: "0 20px",
marginTop: 80,
justifyContent: "flex-start",
marginLeft: 230
}
});
Take a look at the Dashboard example in Page Layout Examples (code). This is a very good example and should help you arrive at a layout for your app.
Regarding the height of the AppBar, the approach is interesting. Rather than specifying a static top margin or padding, they're inserting a div that is styled to be as tall as the AppBar (since its height is responsive and will be different for various viewports):
<div className={classes.appBarSpacer} />
The class appBarSpacer is defined in the stylesheet and uses the toolbar mixin, which exports the exact responsive behavior that is used in Toolbar (and by extension, AppBar):
const styles = theme => ({
// ...
appBarSpacer: theme.mixins.toolbar,
// ...
});
The effect is that there will always be enough space above the main content to push it beneath your AppBar.

React Native FlatList items not rendering

I'm testing a FlatList nested in a Navigator and trying to learn how it works. The code below works fine:
<FlatList
data={[{key: 'a'}, {key: 'b'}]}
renderItem={({item}) => <Text>{item.key}</Text>}
horizontal={true}
/>
But this does not:
<FlatList
data={[{key: 'a'}, {key: 'b'}]}
renderItem={({item}) => <TextComp data={item}/>}
horizontal={true}
/>
TextComp is just a component that displays item.key and it works as intended when tested separately. The code is
<View>
<Text>{this.props.data.key}</Text>
</View>
I've also tried drawing borders around both components and it seems that the FlatList is definitely rendering, but the items are not.
I am testing on my Android device.
Update: I added console.log(this.props) statement to the TextComp component and it displays the props correctly, so the the correct data is being passed from the FlatList to TextComp, but TextComp is just not getting rendered.
Marcel Kalveram got the solution here after I compared his code with mine. Turns out, a height and width are required for the item to render correctly in the FlatList. The explanation I figured for this is that the item's dimensions are required to properly size the item within the FlatList. Similarly, an item's dimensions cannot be percentages since its parent is a FlatList, which has varying dimensions itself. Therefore, the solution to my problem was to add width and height style attributes to the item component. To make it automatically resize, I used built-in React Native Dimensions.

Resources