主页>技术社区>IT 技术>编程开发>软件开发>移动开发

如何在本机Reaction中同步两个平面列表滚动位置

eIT.com.cn 2022/9/23 13:27:37 阅读 90 次

打印


本文介绍了如何在本机Reaction中同步两个平面列表滚动位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如您在上图中看到的,有一个由两列组成的垂直列表。我开发了两个Flat List,因为我无法使用Flat List列选项在一行上设置不同高度的照片样式。

我希望两个平面图具有相同的滚动位置。

我包装了两个FlatList组件以同步滚动。但这里有一个问题。ScllView忽略无限滚动并一次调用所有分页对象。存在性能问题。

如何解决此问题?

这是我的组件代码

import React from 'react';
import { View, Platfrom, Text, StyleSheet, AsyncStorage, TouchableOpacity, Image, FlatList, Button, Dimensions, ScrollView, ListView } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { NavigationActions } from 'react-navigation';
import { connect } from 'react-redux';
import moment from 'moment';

import * as settings from '../../config/settings';
import Menu from '../menu';

import headerStyles from '../../styles/common/header';
import textStyles from '../../styles/common/text';
import containerStyles from '../../styles/common/container';
import imageStyles from '../../styles/common/image';
import boxStyles from '../../styles/common/box';
import objectStyles from '../../styles/common/object';
import commonStyles from '../../styles/common/common';
import colorStyles from '../../styles/common/color';


const window = Dimensions.get('window');

const styles = StyleSheet.create({
    listView: {
        paddingTop: 20,
        backgroundColor: '#FFFFFF',
    },
    fullScreen: {
        flex: 1,
        marginBottom: 50,
    },
    floatView: {
        position: 'absolute',
        width: '90%',
        marginLeft: '5%',
        height: 100,
        bottom: -50,
    },
});

const phoneWidth = Dimensions.get('window').width

class PurchaseListScreen extends React.Component {
    static navigationOptions = ({ navigation }) => {
        const { params = {} } = navigation.state
        return {
            title: '중고 명품 구매',
            headerStyle: headerStyles.header,
            headerTitleStyle: headerStyles.headerTitle,
            headerRight: <Icon name="bars" size={30} color="#333" onPress={() => { params.showModal() }} style={{ padding: 10 }} />,
        }
    }

    constructor(props) {
        super(props);
        this.state = {
            user_token: '',
            refreshing: false,
            isModalVisible: false,
            leftColumneData: [],
            rightColumneData: [],
            leftNextKey: '',
            rightNextKey: '',
        };
        this.hideModal = this.hideModal.bind(this);
    }

    componentDidMount() {
        this.props.navigation.setParams({ showModal: this.showModal });
        this.purchaseListService();
    }

    showModal = () => this.setState({ isModalVisible: true })

    hideModal = () => this.setState({ isModalVisible: false })

    navigate1 = (item) => {
        console.log('click navigate1');
        const navigate1 = NavigationActions.navigate({
            routeName: "home",
        });
        this.props.navigation.dispatch(navigate1);
    };

    purchaseListService = async () => {
        if (this.props.isLoggedIn) {
            let user_info = await AsyncStorage.getItem('user_info');
            get_user_token = JSON.parse(user_info).key;
            this.setState({ user_token: get_user_token });

            const api_uri1 = settings.base_uri + 'purchase-product/odd/'
            const request1 = {
                method: 'GET',
                headers: {
                    'Authorization': 'Token ' + get_user_token,
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            const api_uri2 = settings.base_uri + 'purchase-product/even/'
            const request2 = {
                method: 'GET',
                headers: {
                    'Authorization': 'Token ' + get_user_token,
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            fetch(api_uri1, request1)
                .then(res => res.json())
                .then(res => {
                    this.setState({
leftColumneData: [...res.results],
leftNextKey: res.next
                    })
                })
                .catch((error) => {
                    console.error(error);
                })

            fetch(api_uri2, request2)
                .then(res => res.json())
                .then(res => {
                    this.setState({
rightColumneData: [...res.results],
rightNextKey: res.next,
                    })
                })
                .catch((error) => {
                    console.error(error);
                })

        } else {
            const api_uri1 = settings.base_uri + 'purchase-product/odd/'
            const request1 = {
                method: 'GET',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            const api_uri2 = settings.base_uri + 'purchase-product/even/'
            const request2 = {
                method: 'GET',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            fetch(api_uri1, request1)
                .then(res => res.json())
                .then(res => {
                    this.setState({
leftColumneData: [...res.results],
leftNextKey: res.next,
                    })
                })
                .catch((error) => {
                    console.error(error);
                })

            fetch(api_uri2, request2)
                .then(res => res.json())
                .then(res => {
                    this.setState({
rightColumneData: [...res.results],
rightNextKey: res.next,
                    })
                })
                .catch((error) => {
                    console.error(error);
                })
        }
    }

    onEndReachedService = () => {
        console.log('run onEndReachedService');
        if (this.props.isLoggedIn && this.state.leftNextKey) {
            const api_uri1 = this.state.leftNextKey
            const request1 = {
                method: 'GET',
                headers: {
                    'Authorization': 'Token ' + this.state.user_token,
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            const api_uri2 = this.state.rightNextKey
            const request2 = {
                method: 'GET',
                headers: {
                    'Authorization': 'Token ' + this.state.user_token,
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            fetch(api_uri1, request1)
                .then(res => res.json())
                .then(res => {
                    this.setState({
leftColumneData: [...this.state.leftColumneData, ...res.results],
leftNextKey: res.next
                    })
                })
                .catch((error) => {
                    console.error(error);
                })

            fetch(api_uri2, request2)
                .then(res => res.json())
                .then(res => {
                    this.setState({
rightColumneData: [...this.state.rightColumneData, ...res.results],
rightNextKey: res.next,
                    })
                })
                .catch((error) => {
                    console.error(error);
                })

        } else if (!this.props.isLoggedIn && this.state.leftNextKey){
            const api_uri1 = this.state.leftNextKey
            const request1 = {
                method: 'GET',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            const api_uri2 = this.state.rightNextKey
            const request2 = {
                method: 'GET',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }
            }

            fetch(api_uri1, request1)
                .then(res => res.json())
                .then(res => {
                    console.log('update res1', res);
                    this.setState({
leftColumneData: [...this.state.leftColumneData, ...res.results],
leftNextKey: res.next,
                    })

                })
                .catch((error) => {
                    console.error(error);
                })

            fetch(api_uri2, request2)
                .then(res => res.json())
                .then(res => {
                    console.log('update res2', res);
                    this.setState({
rightColumneData: [...this.state.rightColumneData, ...res.results],
rightNextKey: res.next,
                    })
                })
                .catch((error) => {
                    console.error(error);
                })
        }
    }

    likeService = async (pk, column) => {
        let user_info = await AsyncStorage.getItem('user_info');
        user_token = JSON.parse(user_info).key;
        const api_uri = settings.base_uri + 'purchase-product/' + pk + '/like/'

        var request = {
            method: 'POST',
            headers: {
                'Authorization': 'Token ' + user_token,
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            }
        };

        fetch(api_uri, request)
            .then(res => {
                if(column=='left'){
                    var items = this.state.leftColumneData
                    for (i=0; i<items.length; i++) {
let item = items[i]
if (item.id==pk) {
    item.is_liked = !item.is_liked
    items[i] = item;
    this.setState({ leftColumneData: items })
}
                    }
                } else {
                    var items = this.state.rightColumneData
                    for (i = 0; i < items.length; i++) {
let item = items[i]
if (item.id == pk) {
    item.is_liked = !item.is_liked
    items[i] = item;
    this.setState({ rightColumneData: items })
}
                    }
                }
            })
            .catch((error) => {
                console.error(error);
            });
    }

    renderLabel = (text) => {
        if (text) {
            return (
                <View style={{ backgroundColor: 'red', paddingVertical: 2, marginLeft: 3, marginTop: 5, marginBottom: 8, paddingHorizontal: 4 }}>
                    <Text style={{ color: 'white', fontSize: 9, fontWeight: '400' }}>{text}</Text>
                </View>
            )
        } else {
            return (
                <View style={{ paddingVertical: 2, marginTop: 5, marginBottom: 8, }}>
                </View>
            )
        }
    }

    renderList = (item, column) => {
        return(
            <View>
                <View style={{ 
                    flex: 1, 
                    borderColor: 'rgb(136, 136, 136)', 
                    borderWidth: 1, 
                    marginLeft: 15, 
                    marginTop: 15,
                    backgroundColor: 'white',
                    }}>
                    <TouchableOpacity onPress={()=>{}}>
                    {item.is_vertical?
<Image
    source={{ uri: item.first_thumbnail }}
    style={{ flex:1, height: 210 }}/>
:
<Image
    source={{ uri: item.first_thumbnail }}
    style={{ flex: 1, height: 130 }} />
                    }
                    </TouchableOpacity>
                    <View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row' }}>
    <TouchableOpacity style={{ flex: 4 }}>
        <Text style={{
            fontSize: 14,
            fontWeight: '600',
            color: 'rgb(35, 31, 32)',
            marginTop: 10,
            marginLeft: 8
        }}>{item.name}</Text>
        <Text style={{
            fontSize: 12,
            fontWeight: '500',
            color: 'rgb(35, 31, 32)',
            marginLeft: 8,
            marginTop: 8
        }}>{item.partner.biz_name}</Text>
        <View style={{ flexDirection: 'row', marginLeft: 6 }}>
            {this.renderLabel(item.product_type_str)}
            {this.renderLabel(item.city.name)}
        </View>
    </TouchableOpacity>

    <View
        style={{ flex: 1, marginTop: 10, marginRight: 2, alignItems: 'center' }}>
        {this.props.isLoggedIn ? 
            <View>
                {item.is_liked ?
                    <Icon
name="heart" size={17} color="red"
onPress={() => {
    this.likeService(item.id, column);
}} />
                    : <Icon name="heart-o" size={17} color="red"
onPress={() => {
    this.likeService(item.id, column);
}} />
                }
            </View> : 
            <View>
                <Icon name="heart-o" size={17} color="red"
                    onPress={() => {
console.log('press heart', column);
                    }} />
            </View>}
    </View>

</View>
<View style={[ colorStyles.greenBackground,
    {
        flex: 1,
        borderTopWidth: 1,
        borderColor: 'rgb(136, 136, 136)',
        padding: 5,
        paddingRight: 10,
    }]}>
    <Text style={{ 
        textAlign: 'right',
        fontSize: 14,
        fontWeight: '500',
        color: 'rgb(35, 31, 32)',
    }}>
        {(item.price).toString().replace(/B(?=(d{3})+(?!d))/g, ",")}원 {item.id}
    </Text>
</View>
                    </View>
                </View>
            </View>
        )
    }

    render() {   
        return (
            <View style={{ flex: 1 }}>
                <Menu hideModal={this.hideModal.bind(this)} isVisible={this.state.isModalVisible} navigation={this.props.navigation} />
                <View style={{ flexDirection: 'row' }}>
                    <FlatList
style={{ flex: 1 }}
showsVerticalScrollIndicator={false}
initialNumToRender={20}
onEndReachedThreshold={1}
onEndReached={this.onEndReachedService}
refreshing={this.state.refreshing}
onRefresh={this.purchaseListService.bind(this)}
data={this.state.leftColumneData}
renderItem={({ item }) => this.renderList(item, column='left')}
keyExtractor={(item) => item.id}
                    />
                    <FlatList
style={{ flex: 1, paddingRight: 15  }}
showsVerticalScrollIndicator={false}
refreshing={this.state.refreshing}
onRefresh={this.purchaseListService.bind(this)}
data={this.state.rightColumneData}
renderItem={({ item }) => this.renderList(item, column='right')}
keyExtractor={(item) => item.id}
                    />
                </View>
            </View>
        )
    }
}


const mapStateToProps = state => ({
    isLoggedIn: state.loginReducer.isLoggedIn
})

const PurchaseList = connect(mapStateToProps, null)(PurchaseListScreen);

export default PurchaseList;

推荐答案

您可以尝试使用此代码平行滚动两个平面。

     <ScrollView contentContainerStyle={{flexDirection:"row"}}>
        <Flatlist
          ...
          scrollEnabled={false}
        />
        <Flatlist
          ...
          scrollEnabled={false}
        />
     </ScrollView>

这篇关于如何在本机Reaction中同步两个平面列表滚动位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!






相关内容


热门栏目


特别声明


最新资讯
热讯排行



合作媒体友情链接
生活常识小贴士 软件开发教程 智慧城市生活网 息县通生活服务[移动版] 息县商圈[移动版] 美食菜谱
健康养生 法律知识 科技频道 电影影讯 留学考研学习 星座生肖|解梦说梦




关于我们 | 联系我们 | 合作媒体 | 使用条款 | 隐私权声明 | 版权声明

      Copyright © 2023 eIT.com.cn. All Rights Reserved. 豫ICP备2022012332号