0

I'm trying to implement auto scroll in a ScrollView, but somehow can't figure the proper way of doing it, my idea, was something like, if I add an item and the contentSize overflows the ScrollView width I should scroll to the end, if I remove an item and the contentSize is smaller than the ScrollView width I should scroll to the start.

Here's what I have so far

    <ScrollView
      horizontal
      showsHorizontalScrollIndicator={false}
      ref={(scrollView) => {
        this.scrollView = scrollView;
      }}
      onLayout={(e) => {
        this.layoutWidth = e.nativeEvent.layout.width;
      }}
      onContentSizeChange={(contentWidth, contentHeight) => {
        this.scrollView.scrollTo({
          x: contentWidth > this.layoutWidth ? contentWidth + this.layoutWidth - width : 0,
          y: 0,
          animated: true,
        });
      }}>
      {contacts.map((contact) => (
        <SelectedContacsItem
          contact={contact}
          onRemoveContactPress={onRemoveContactPress}
          key={contact.id}
        />
      ))}
    </ScrollView>

This doesn't work for the remove items process, on the last items(when the content gets smaller than the view) it moves the content to random positions, I added the onScroll prop and watched the logs from there and seems that the contentOffSet is the issue because it has random values(sometimes negative values other times big numbers), not sure how to solve it.

Alex
  • 6,849
  • 6
  • 19
  • 36
  • what auto-scroll needs to do? for example, i have 3 items, you want to move for one to another? – Idan Nov 04 '19 at 16:26
  • @idan you have a list, if the screen size is bigger than the list size you don't scroll, once it overflows it should scroll to the right, once it decreases back to a size smaller than the screen the items should be at left – Tiago Correia Nov 06 '19 at 09:14
  • Tell me if i understand right - you show the list in a horizontal way, if the list bigger then the width of the screen you want to scroll automatically to the end of the screen ? – Idan Nov 06 '19 at 09:20
  • @Idan right, if it then decreases the size again to a size smaller than the screen keep the content at left instead of right – Tiago Correia Nov 07 '19 at 09:22
  • I attached answer with code – Idan Nov 07 '19 at 13:34

1 Answers1

1

I do something like this before a week and i recommended to you (like me) to give up on ScrollView and map in this case

<FlatList
   ref={ref => this.flatListRef = ref}
   horizontal
   data={contact}
   extraData={this.state}
   keyExtractor={(item, index) => index}
   renderItem={({ item, index }) => <SelectedContacsItem
      contact={item}
      onRemoveContactPress={onRemoveContactPress}
      key={item.id}
      index={index}
    />}
/>

And the function onRemoveContactPress handle the scroll with the scrollToIndex property (don't forget to pass index)

onRemoveContactPress = (index) => {
    this.flatListRef.scrollToIndex({ animated: true, index: index });
}
  • if scrollToIndex don't scroll to the right index try to change index to something else ('play' with this)
  • in my case for example it's in RTL direction so it look like this: index: this.state.contact.length - index - 1
Idan
  • 3,604
  • 1
  • 28
  • 33
  • Thanks for your input @idan, will test it properly and let you know how it goes – Tiago Correia Nov 08 '19 at 09:17
  • tested some options but can't come with the "perfect" solution, not sure if you are familiar with the messenger group creation behaviour, but if you can give it a try and look into the behaviour of the selected contacts being added or removed – Tiago Correia Nov 11 '19 at 12:33
  • What not working for you? and what the behavior now (with my code)? – Idan Nov 11 '19 at 13:31