React-Native 使用 Flatlist 滚动到顶部

React-Native scroll to top with Flatlist

我在滚动到 Flatlist 的顶部时遇到了很多问题,因此非常感谢您的帮助!

基本上它从 firebase 获取前 5 个项目,然后在调用 onEndReached 时我们将接下来的 5 个项目附加到列表中:

data: [...this.state.data, ...results]

现在我的视图顶部有一个刷新按钮,它执行以下操作:

this.flatListRef.scrollToOffset({ animated: true, y: 0 });

如果我在呈现前 5 个项目时单击此按钮,它将按预期滚动到列表顶部。该问题仅在列表附加到(我猜这些项目不在视图中?)后才会出现。

我也试过 'ScrollToItem' 但是我猜这行不通是因为 React Native 文档中的以下内容:

Note: Cannot scroll to locations outside the render window without specifying the getItemLayout prop.

任何人都可以解释发生了什么或知道我做错了什么吗?

提前致谢!

getItemLayout:(不完全确定这是做什么的或如何计算长度和偏移量等)

getItemLayout = (data, index) => (
{ length: 50, offset: 50 * index, index }
)

return (
  <View>
    <FlatList
      ref={(ref) => { this.flatListRef = ref; }}
      onScroll={this.handleScroll}
      data={this.state.data}
      keyExtractor={item => item.key}
      ListFooterComponent={this.renderFooter()}
      onRefresh={this.handleRefresh}
      refreshing={this.state.newRefresh}
      onEndReached={this.handleEndRefresh}
      onEndReachedThreshold={0.05}
      getItemLayout={this.getItemLayout}
      renderItem={this.renderItem}
    />
    {this.state.refreshAvailable ? this.renderRefreshButton() : null}
  </View>
);

正确的语法是

this.flatListRef.scrollToOffset({ animated: true, offset: 0 });

你也可以使用

scrollToIndex

以防万一有人不知道如何使用钩子来做到这一点,这里有一个例子

function MyComponent() {
    const flatListRef = React.useRef()

    const toTop = () => {
        // use current
        flatListRef.current.scrollToOffset({ animated: true, offset: 0 })
    }

    return (    
        <FlatList
            ref={flatListRef}
            data={...}
            ...
        />
    )
}

主要区别在于您可以通过 .current

访问它

对于反应钩子

  1. import React, {useRef} from 'react'
  2. 声明它 -> const flatListRef = useRef()
  3. 设置为ref={flatListRef}
  4. 可以这样称呼它 flatListRef.current.scrollToOffset({animated: false, offset: 0})

在这个回答中,我提到了一个非常简单的代码片段,其中有 2 个按钮可以向右或向左滚动 flatlist。您可以使用此代码实现编程滚动平面列表的其他用例。

//import
import React, { useEffect, useState, useRef, useCallback } from 'react';

//React class declaration.
const DocumentsInfo = ({ route, navigation }) => {
  
  //state variable
  const [documentsArray, setDocumentsArray] = useState({}); // array being shown in flatlist.
  const [maxVisibleIndex, setMaxVisibleIndex] = useState(0); // highest visible index currently visible.
  const [minVisibleIndex, setMinVisibleIndex] = useState(0); // lowest visible index currently visible.
  const flatListRef = useRef() // reference of flatlist.

  // callback for whenever flatlist scrolls
  const _onViewableItemsChanged = useCallback(({ viewableItems, changed }) => {
     setMaxVisibleIndex(viewableItems[viewableItems.length - 1].index);
     setMinVisibleIndex(viewableItems[0].index);
  }, []);

  // function for scrolling to top
  const scrollToTop = () => { 
    setMinVisibleIndex(0);
    setMaxVisibleIndex(0);
    flatListRef.current.scrollToIndex({ index: 0, animated: true });
  };

  // function for scrolling to bottom
  const scrollToBottom = () => { 
    let temp = documentsArray.length - 1;
    setMinVisibleIndex(temp);
    setMaxVisibleIndex(temp);
    flatListRef.current.scrollToIndex({ index: temp, animated: true });
  };

  // function for moving flatlist left and right by 1 index
  const moveNextPreviousHorizontalFlatlist = (isNext) => {
     if (isNext) {
        let maxVisible = maxVisibleIndex + 1;
        if (maxVisible < documentsArray.length) {
           let minVisible = minVisibleIndex + 1;
           setMinVisibleIndex(minVisible);
           setMaxVisibleIndex(maxVisible);
           flatListRef.current.scrollToIndex({ index: maxVisible, animated: true });
        }
     }
     else {
        let minVisible = minVisibleIndex - 1;
        if (minVisible >= 0) {
           let maxVisible = maxVisibleIndex - 1;
           setMinVisibleIndex(minVisible);
           setMaxVisibleIndex(maxVisible);
           flatListRef.current.scrollToIndex({ index: minVisible, animated: true });
        }
      }
   };

   // UI 
   return (
       <View>
       { maxVisibleIndex != documentsArray.length - 1 &&
          <View style={styles.Refresh}>
            <TouchableOpacity onPress={() =>
               moveNextPreviousHorizontalFlatlist(true)
            }>
             <Image style={styles.Refresh} source={Refresh} />
            </TouchableOpacity>
           </View>
       }

       <FlatList
         ref={flatListRef}
         onViewableItemsChanged={_onViewableItemsChanged}
         showsHorizontalScrollIndicator={false}
         horizontal
         keyExtractor={(item, index) => item.fileName + index}
         data={documentsArray}
         renderItem={({ item, index }) => {
           return (  <DocumentListItem /> )
         }}
       />

       { minVisibleIndex != 0 &&
         <View style={styles.Refresh}>
           <TouchableOpacity onPress={() =>
              moveNextPreviousHorizontalFlatlist(false)
            }>
             <Image style={styles.Refresh} source={Refresh} />
           </TouchableOpacity>
         </View>
       }
     </View>
     );