react-navigation-collapsible icon indicating copy to clipboard operation
react-navigation-collapsible copied to clipboard

When used together with FlatList as per instruction, RefreshControl renders under the navigation header.

Open joonhocho opened this issue 5 years ago • 8 comments

Information

  • react-native version: 0.62.2 (latest)
  • react-navigation version: 5.5.0 (latest)
  • react-navigation-collapsible version: 5.6.1 (latest)
  • Platform (iOS/Android): iOS
  • react-native init or Expo: react-native init

Detail

When used together with FlatList as per instruction, RefreshControl renders under the navigation header. Screen Shot 2020-06-02 at 2 52 57 AM

joonhocho avatar Jun 02 '20 09:06 joonhocho

@joonhocho I have same problem. Did you find any solution?

amin79 avatar Jun 15 '20 21:06 amin79

There is progressViewOffset for FlatList but it's only for Android. It seems to be a very old issue of RN. https://react-native.canny.io/feature-requests/p/offsetting-refreshcontrol-on-ios-via-progressviewoffset

I will get back to here if I find a workaround or a solution.

benevbright avatar Jun 15 '20 22:06 benevbright

https://stackoverflow.com/questions/56969502/progressviewoffset-for-ios-refresh-control-react-native This SOF answer says that we can use contentInset.

benevbright avatar Jun 15 '20 22:06 benevbright

I encountered the same problem. Replacing the padding with contentInset only for iOS and creating a custom RefreshControl with progressViewOffset only for android worked on a standard FlatList.

However, I then ran into problems with my SectionList: the section header was also rendered with the contentInset. I did not manage to counter this and was not satisfied with all the platform specific exceptions in my components.

As an alternative solution, I applied the translateY animated value from the useCollapsibleStack hook to my SectionList as a whole. This in turn required me to apply the containerPaddingTop to the contentContainer bottom padding to prevent the list from getting cut off at the bottom.

  const {
    onScroll,
    scrollIndicatorInsetTop,
    containerPaddingTop,
    translateY,
  } = useCollapsibleStack()

  return (
    <Animated.SectionList
      // other props
      onScroll={onScroll}
      scrollIndicatorInsets={{ bottom: scrollIndicatorInsetTop }}
      contentContainerStyle={{ paddingBottom: containerPaddingTop }}
      scrollEventThrottle={16} // without this, it can get jittery.
      style={{
        transform: [
          {
            translateY: translateY.interpolate({
              inputRange: [0, containerPaddingTop],
              outputRange: [containerPaddingTop, 2 * containerPaddingTop],
            }),
          },
        ],
      }}
    />
  )

isilher avatar Jul 14 '20 17:07 isilher

I encountered the same problem. Replacing the padding with contentInset only for iOS and creating a custom RefreshControl with progressViewOffset only for android worked on a standard FlatList.

However, I then ran into problems with my SectionList: the section header was also rendered with the contentInset. I did not manage to counter this and was not satisfied with all the platform specific exceptions in my components.

As an alternative solution, I applied the translateY animated value from the useCollapsibleStack hook to my SectionList as a whole. This in turn required me to apply the containerPaddingTop to the contentContainer bottom padding to prevent the list from getting cut off at the bottom.

  const {
    onScroll,
    scrollIndicatorInsetTop,
    containerPaddingTop,
    translateY,
  } = useCollapsibleStack()

  return (
    <Animated.SectionList
      // other props
      onScroll={onScroll}
      scrollIndicatorInsets={{ bottom: scrollIndicatorInsetTop }}
      contentContainerStyle={{ paddingBottom: containerPaddingTop }}
      scrollEventThrottle={16} // without this, it can get jittery.
      style={{
        transform: [
          {
            translateY: translateY.interpolate({
              inputRange: [0, containerPaddingTop],
              outputRange: [containerPaddingTop, 2 * containerPaddingTop],
            }),
          },
        ],
      }}
    />
  )

Android: It starts fluctuating / jitter screen while scrolling even different values of scrollEventtrottle is not solving it.

saadi-ninjasCode avatar Jul 22 '20 09:07 saadi-ninjasCode

You're right! I'm not sure how I missed this on my initial tests but it indeed jitters quite a lot. It seems the android scroll gesture does not like us moving the list up and down during the scroll motion.

I did not find a good common solution so I ended up splitting my component into:

AnimatedSectionList.ios.tsx which uses the above transelateY hack.

AnimatedSectionList.android.tsx which uses the default collapsible header config and adds the progressViewOffset to a custom refreshControl as suggested by Bright.

isilher avatar Jul 28 '20 15:07 isilher

Sorry about it. FYI, the jittering issue is RN's very old bug. https://github.com/facebook/react-native/issues/21801 If this bug was not present, this library would have had a lot more potential because it could have built in a much better way than using absolute position header. I only can tell you there are many limitations in this library. I had tried to fix RN some time ago but only found out that the RN issue is not easy to fix due to its bad design and race conditions.

benevbright avatar Aug 01 '20 20:08 benevbright

On Android, use progressViewOffset prop.

progressViewOffset={paddingHeight}               

On iOS, In the following props, use what you need.

contentInset={{ top: paddingHeight }}
contentContainerStyle={{ paddingTop: Platform.OS === 'ios' ? 0 : paddingHeight }}
contentOffset={{ y: -paddingHeight }}

wayne-tt avatar Aug 04 '20 09:08 wayne-tt