Setting an initial scroll position of a React Native ListView - react-native

I'm trying to set the initial scroll position of a ListView in react native.
Right now, I'm doing this:
componentDidMount() {
let i = this.props.images.indexOf(this.props.current);
if(i != -1) {
this.refs.listView.scrollTo({ x:i*this.props.width, y:0, animated:false });
}
}
where the images prop is the datasource for the ListView, the current prop is where I want to be initially scrolled to, and the width prop is the width of the component. (The component scrolls horizontally).
This works, but there's a delay between the initial render and the call to componentDidMount, giving me a flash of the end of end of the list before the list is scrolled.
Is there a way of setting an initial scroll position of the list? Or better way of doing this to get rid of that flash?

On iOS you can use the ScrollView#contentOffset to set the initial scroll position of a ListView, which inherits the properties of ScrollView.
If you are looking for an Android solution, the ListView.scrollTo method you are calling seems like the best bet for the general case.
That said, if I interpret your code sample correctly, you are using the ListView for a paginated, horizontal list, perhaps with the help of the pagingEnabled property? If this is the case, on Android you might look at using ViewPagerAndroid instead, and setting the initialPage property.

Related

Get the position of a fading component in react native

The situation:
I am building a tooltip that has to programmatically position itself based on an avatar component that lives in a different package.
The avatar lives in the header part of the screen and I can't colocate the tooltip to be next to it code-wise, because the tooltip needs to be dismissed once the user interacts/touches the screen.
The Problem:
is that I can't just use onLayout event on the avatar because it fades into the view and the layout event always results in { x: 0, y: 0 }, which is not accurate and doesn't reflect the actual position of the avatar.
Thanks in advance for any help or advice that you can offer!
What I tried:
Passing a callback for onLayout, but as I mentioned above it doesn't return the correct values.
Using the measure function, but it resulted in the same values as onLayout.
Using the PanResponder on that avatar and requested to respond to move events, but because the avatar doesn't move the onPanResponderMove doesn't get triggered.

How to stay in position when new messages are loaded in a ScrollView in React-Native?

I have a ScrollView containing messages (most recent messages are further) in a chat application.
I limit the number of pre-loaded messages, and I dynamically load a new batch when the Scroll View is scrolled to the top. So when new messages are loaded, the current scrollPos is at 0.
The problem is that when the new messages arrive, the scrollPos stays at 0, so the user is teleported to the oldest newly loaded message.
I have tried to deal with it by manually scrolling back down to the position using the size of the content change, but this is not satisfying as the user sees a back and forth scrolling.
Can someone think of a way to do this so that the user does not see any change when the new messages appear an can simply gradually scroll up to see them.
I found a way to do it.
The idea comes from the Invertible Scroll View component: https://github.com/expo/react-native-invertible-scroll-view
I didn't use the component but implemented the idea directly on the Scroll View to have minimal changes in my code.
To explain, we translate vertically the Scroll View using the style of the Scroll View and transform: [{ scaleY: -1 }]. We do the same for the children. Then, we revert the order of the messages.
In that setup, the scrollPos() measures from the visual bottom. To trigger the loading of the new messagges, now I use
const isCloseToBottom = ({layoutMeasurement, contentOffset, contentSize}) => {
const paddingToBottom = 20;
return layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom;
};
The trick is that now, when the new messages appear on top, you have nothing to do as the distance from the user's point of view to the bottom does not change.
You can use the onContentSizeChange prop to scroll to the bottom anytime it detects a change in content size.
The scrollToEnd function may differ depending on RN version.
<ScrollView
...
onContentSizeChange={() => this.scrollView.scrollToEnd({animated: true})}>
</ScrollView>
Ref: https://reactnative.dev/docs/scrollview#scrolltoend

React Native - Set parent match width for component inside a ScrollView that is inside a Modal

I have a Modal with a ScrollView inside and some items inside the ScrollView. When the Modal popped up, the item's border is not aligned to the Modal's border. Some components like TextInput become thinner and some is overflow. It's not like this outside of Modal.
This can be solved by setting component's offset explicitly relative to Dimensions.get('window').width. But I just want an implicit solution.
I've done trying setting style properties for ScrollView's contentContainerStyle and also putting a wrapper View inside the ScrollView. None of them works.
I've made it after wrap ScrollView with a View with style flexDirection : 'row'. Yet to figure out why

Prevent pull-to-refresh for ScrollView in react-native

Is there a way to prevent pull-to-refresh functionality for ScrollView component?
I want to be able scroll, but I don't wanna allow to pull down content of component and prevent situations like this:
You seem like you have placed the View containing you custom made action bar inside the scroll view, and what's happening in the image you provided isn't caused by pull-to-refresh it's provided by overscrolling so you got 2 solutions:
1-Place your action bar outside your ScrollView and make the action bar and the ScrollView childrens of 1 View.
2-Add alwaysBounceVertical={false} to your ScrollView props.
Hope this helps.
use a const refreshing = false , initially. Then on call of _onRefresh , change refreshing from false to true, and reinitialise the content of the scollview.

How can I implement animate on page scroll?

When a user scrolls through a webpage, how can I trigger animate css?
Is it a matter of when v-show="element" appears, trigger x?
Using Vue 2 + animate css
I found answer from Ikbel useful
How to display and transition when scroll position reaches element position in the screen?
you can achive this with custom directive which adds binding inViewport for window scroll event to elements that you want to animate.
I added data-transition to html element that I want to animate
<div v-vpshow data-transition="flipInX"><div>
and changed binding like this
el.$onScroll = function() {
if (binding.def.inViewport(el)) {
el.classList.add('animated')
el.classList.add(el.getAttribute('data-transition'))
el.classList.remove('before-enter')
binding.def.unbind(el, binding)
}
}