eclipsesource / tabris-js

Create native mobile apps in JavaScript or TypeScript.
https://tabrisjs.com
BSD 3-Clause "New" or "Revised" License
1.4k stars 170 forks source link

Improve pull-to-refresh UX when using ScrollView #1827

Open cpetrov opened 5 years ago

cpetrov commented 5 years ago

Problem description

Currently, the only possibility to use pull-to-refresh with ScrollView is wrapping it in a RefreshComposite. AScrollView wrapped in a RefreshComposite behaves differently than a CollectionView regarding pull-to-refresh.

When the ScrollView hasn't yet been scrolled to top and pulling down beyond the minimal scroll offset, the ScrollView will overscroll instead of initiating the pull-to-refresh action.

When using a CollectionView in the same scenario, the pull-to-refresh action will be triggered instead of overscrolling, which is the more natural and expected UX.

RefreshComposite > ScrollView CollectionView
scrollComposite collectionView

Expected behavior

Instead of overscrolling, ScrollView wrapped inside of a RefreshComposite with refreshEnabled: true should always trigger the pull-to-refresh action when pulling down beyond the minimal scroll offset. If this is technically not possible, would it be possible to introduce a more natural pull-to-refresh behavior, similarly to the one used with CollectionView, on ScrollView itself?

Environment

Code snippet

import {RefreshComposite, ScrollView, TextView, contentView} from 'tabris';

contentView.append(
  <RefreshComposite left={0} top={0} right={0} bottom={0} onRefresh={hideIndicatorAfterDelay}>
    <ScrollView left={0} top={0} right={0} bottom={0}>
      {Array.from(new Array(20).keys()).map((i) => (
        <TextView left={8} top='prev() 48' right={8} text={`${i} Label`}/>
      ))}

    </ScrollView>
  </RefreshComposite>
)

function hideIndicatorAfterDelay({target}: {target: RefreshComposite}) {
  setTimeout(() => {
    target.refreshIndicator = false;
  }, 2000);
}
patrykmol commented 5 years ago

After investigating this issue I believe that the only way to move forward is to implement refresh logic into ScrollView. This however duplicates functionality of RefreshComposite more or less. RFC.