How can I keep position on ScrollView or ListView?
Asked Answered
D

2

6

When you use ScrollView or ListView in your ReactNative app and some new data came in, the default behavior of them is to keep the position in the Scroll component. Which means if the new data of height 20 came in when you're at the middle of the ScrollView, on-screen items will slide by 20 and sometimes it will go off the screen.

Is there any way to keep/track the position? for example, if the new data of height 20 came in, the position automatically adjust the position by 20 so that current on screen items keep on the screen. Thanks in advance.

Diantha answered 21/12, 2016 at 19:57 Comment(2)
This might help you https://mcmap.net/q/157151/-is-it-possible-to-keep-a-scrollview-scrolled-to-the-bottomGavette
@HenrikR Yea thats definitely a alternative way of doing it but it's calling the position change in onContentSizeChange, which means it adjust the position after the content size has already changed and would change the position after that so it's gonna come up against bad UX.Diantha
S
4

I have a working solution, although it's not very smooth, it does the job:

handleScroll = (event) => {
  this.scroll = event.nativeEvent.contentOffset.y
  if (this.ready && this.scroll < SCROLL_TRIGGER) {
    // load more stuff here
  }
}

handleSize = (width, height) => {
  if (this.scroll) {
    const position = this.scroll + height - this.height
    this.refs.sv.scrollTo({x: 0, y: position, animated: false})
  }
  this.height = height
}

// render:

<ScrollView ref="sv"
  scrollEventThrottle={16}
  onScroll={this.handleScroll}
  onContentSizeChange={this.handleSize}
>
  {content}
</ScrollView>

If someone made something smoother, let us know!

Subtotal answered 8/8, 2017 at 10:40 Comment(6)
thanks and I think you're right, although it's not very smooth, it does the job, for the use case of mine, I pull down to load previous page content, the handleSize actually fires after the content has been rendered. So the user experience is user sees the top item and then be brought back to the original position where he was. This is really not good, but couldn't find a better approach, so I take yours. Thank you.Chet
@Chet did u find any better approach?Faithfaithful
I juat made animated:true so that it doesn't look like a glitchFaithfaithful
@ZeeshanAhmadKhalil good work around. But how can it be done better? Smooth like scrolling a whatsapp chat to the top?Auricle
@YannickSchröder use FlatList instead of scrollviewFaithfaithful
const [dheight, setHeight] = useState({}); const scroll = useRef(null) const onScroll = ({nativeEvent}) =>{ if(nativeEvent.contentOffset.y > 1){ setHeight(nativeEvent.contentSize.height) } } const handleSize = (width, height) => { if (dheight > 0) { const position = height - dheight scroll.current.scrollTo({x: 0, y: position, animated: false}) } } this work for me. i use this for chat box. this work append new data top.Effectual
P
1

More elegant sulotion:

<ScrollView
    ref={(ref => this.scrollViewRef = ref)}
    onScroll={event => { this.yOffset = event.nativeEvent.contentOffset.y }}
    onContentSizeChange={(contentWidth, contentHeight) => { this.scrollViewRef.scrollTo({ x: 0, y: this.yOffset, animated: false }) }}>
Perk answered 28/7, 2019 at 11:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.