【问题标题】:How to scroll FlatList to some index immediately after scrolling?滚动后如何立即将 FlatList 滚动到某个索引?
【发布时间】:2021-07-17 10:29:06
【问题描述】:

如何在拖动 FlatList 后将FlatList 组件滚动到某些索引/子级?

For Example:

正如我们在 Youtube/TikTok 故事中看到的那样,当我们拖动屏幕时,下一个视频会立即出现在它之后。所以,我用 FlatList 来实现它,如果我们拖动下面的项目,那么 FlatList 应该移动到上面的项目/索引。所以,我正在做的是存储当前显示的索引和 onScrollEndDrag 道具,我正在检查 Y 的位置,并相应地运行 scrollToIndex 函数,但它不起作用。

Reason

因为在拖动后滚动时,FlatList 会忽略 scrollToIndex 函数。

他们有没有人帮我解决这个问题???

import React from 'react';
import { View, Text, StyleSheet, AppState, FlatList, Animated, Dimensions } from 'react-native';
import fetchDataFromDirectory from '../data/fetchDataFromWhatsApp';
import PlayerVideo from '../components/VideoPlayer';
import Image from '../components/Image';

const { width, height } = Dimensions.get('window');

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

class VideoScreen extends React.Component {
    state = {
        pdfInfo: [], //[{id, name, path},...]
        appState: '',
        viewableIndex: 0
    }

    fetchData = async () => {
        const data = await fetchDataFromDirectory('videos');
        this.setState({ pdfInfo: data.pdfInfo });
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.state.pdfInfo.length > this.dataLength) { //We are seeing if we need to scroll to top or not
            this.dataLength = this.state.pdfInfo.length;
            try {
                this.list.scrollToIndex({ animated: true, index: 0, viewPosition: 0 })
            } catch (err) {

            }
        }
    }

    handleAppStateChange = (nextAppState) => {
        //the app from background to front
        if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
            this.fetchData();
        }
        //save the appState
        this.setState({ appState: nextAppState });
    }

    componentDidMount() {
        this.videoHeight = height;
        this.dataLength = 0;
        this.fetchData();
        AppState.addEventListener('change', this.handleAppStateChange);
    }

    onViewableItemsChanged = ({ viewableItems, changed }) => {
        // console.log("Visible items are", viewableItems);
        // console.log("Changed in this iteration", changed);
        try {
            this.setState({ viewableIndex: viewableItems[0]['index'] })
        } catch (err) {

        }
    }

    componentWillUnmount() {
        AppState.removeEventListener('change', this.handleAppStateChange)
    }

    render() {
        return <AnimatedFlatList
            onLayout={(e) => {
                const { height } = e.nativeEvent.layout;
                this.videoHeight = height;
            }}
            // onResponderRelease={e => {console.log(e.nativeEvent.pageY)}}
            // onResponderRelease={(e) => console.log(e.nativeEvent.)}
            // onScrollBeginDrag
            // snapToAlignment={'top'}
            // onMoveShouldSetResponderCapture={(e) => {e.nativeEvent.}}
            // decelerationRate={'fast'}
            decelerationRate={'fast'}
            scrollEventThrottle={16}
            // onScroll={(e) => console.log('+++++++++++++++++',Object.keys(e), e.nativeEvent)}
            onScrollEndDrag={(e) => {
                // this.list.setNativeProps({ scrollEnabled: false })
                console.log(e.nativeEvent)
                if (e.nativeEvent.velocity.y > 0.1) {
                    console.log('go to above')
                    this.list.scrollToIndex({animated: true, index: this.state.viewableIndex - 1, viewPosition: 0})
                } else if (e.nativeEvent.velocity.y < -0.9){
                    console.log('go to below')
                    this.list.scrollToIndex({animated: true, index: this.state.viewableIndex + 1, viewPosition: 0})
                } 
                // if (e.nativeEvent.velocity.y < 0.1000 && e.nativeEvent.velocity.y >= 0) {
                //     this.list.scrollToIndex({animated: true, index: this.state.viewableIndex, viewPosition: 0})
                // }
                // else if (e.nativeEvent.velocity.y < -0.1000 && e.nativeEvent.velocity.y < 0) {
                //     this.list.scrollToIndex({animated: true, index: this.state.viewableIndex, viewPosition: 0})
                // }
                // this.list.setNativeProps({ scrollEnabled: true })
                console.log('h1')
            }}
            viewabilityConfig={{
                // itemVisiblePercentThreshold: 90,
                viewAreaCoveragePercentThreshold: 60
            }}
            // extraData={this.state.viewableIndex}
            onViewableItemsChanged={this.onViewableItemsChanged}
            // scr
            contentContainerStyle={styles.screen}
            data={this.state.pdfInfo}
            keyExtractor={item => item.id}
            ref={ref => this.list = ref}
            renderItem={({ item, index }) => {
                // console.log(index)
                return <PlayerVideo
                    source={item.path}
                    refList={this.list}
                    height={this.videoHeight}
                    index={index}
                    isViewable={this.state.viewableIndex == index ? true : false} />
            }}
                </View>
            }}
        />
    }
}

export default VideoScreen;

const styles = StyleSheet.create({
    screen: {
        backgroundColor: '#111212',
        // flex: 1
    }
})

【问题讨论】:

    标签: react-native react-native-flatlist


    【解决方案1】:

    首先将引用 flatListRef 添加到平面列表中:

    <Flatlist
         ref={(ref) => this.flatListRef = ref}
         data={data}
         keyExtractor={keyExtractor}
         renderItem={renderItem}
         onScrollBeginDrag={onBeginScroll}/>
    />
    

    然后如下定义onScrollBeginDrag函数滚动到特定索引:

    onBeginScroll = () => {
        this.flatListRef._listRef._scrollRef.scrollToIndex({ animating: true, index: [YOUR_INDEX_HERE] });
    }
    

    是的,您应该访问元素 _listRef 然后 _scrollRef 然后调用 scrollToIndex


    • 反应原生 0.64.1
    • 反应 17.0.2

    【讨论】:

    • 从哪里可以得到_listRef和_scrollRef???我只有平面列表参考...
    • 当用户松开手指时,我想滚动到下一个/上一个索引。如果我们在 onScrollBeginDrag 中做 scrollToIndex,那将是最糟糕的 UI。
    • 通过添加您的参考:&lt;Flatlist ref={(ref) =&gt; this.flatListRef = ref}
    • 已经完成!但 _listRef 和 _scrollRef 不存在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多