反应本地-折叠表

时间:2020-06-11 08:06:22

标签: android ios react-native

我计划制作一张折叠桌。您可以在此link

中找到它

我尝试过:

  • 为列名使用自定义组件,为第一列使用FlatList
  • 在其余列中使用“节”列表

================================================ =============
| _____自定义组件_____ | __________部分列表标题__________ |
| ================================================= ========== |
| _________平面清单____________ | __________节列表正文____________ |
| ================================================= ========== ||

我能够使列表一起滚动。但是,如果列表中有450多个行,则性能将大大降低。

如果您有任何解决方案,请告诉我。

谢谢你!

1 个答案:

答案 0 :(得分:0)

我找到了一种方法。这个想法是。

  1. 使用Animated.ScrollView控制水平滚动
  2. 使用FlatList来控制垂直滚动
  3. 进行水平滚动时,保留FlatList的第一个元素,然后移动其余元素。

下面是代码:

import React, {Component} from 'react';
import {Animated, FlatList, StyleSheet, Text, View,} from 'react-native';
import * as UIConfig from "../../../../configs/UIConfig";
import * as ColorConfig from "../../../../configs/ColorConfig";

export interface CollapseTableColumnType {
    name: string,
    accessName: string,
    width: number,
    visible: boolean,
}

interface CollapseTableType {
    normalColumns: Array<CollapseTableColumnType>,
    collapseColumns: Array<CollapseTableColumnType>,
    data: Array<any>
}

interface State {
    scrollX: Animated.Value,
}

class CollapseTable extends Component<CollapseTableType, State> {

    // Data

    private _scrollView: any = null;
    private _flatList: FlatList<any> | null = null;

    static defaultProps: CollapseTableType = {
        normalColumns: [],
        collapseColumns: [],
        data: [],
    };

    state: State = {
        scrollX: new Animated.Value(0),
    };

    private _HEADER_SCROLL_DISTANCE = this.props.collapseColumns.concat(this.props.normalColumns)
        .reduce((totalWidth, currentWidth) => currentWidth.width + totalWidth, 0);

    private _headerTranslate = this.state.scrollX.interpolate({
        inputRange: [0, this._HEADER_SCROLL_DISTANCE],
        outputRange: [0, this._HEADER_SCROLL_DISTANCE],
        extrapolate: 'clamp',
    });

    scrollToTop = () => {
        if (this._flatList) {
            this._flatList.scrollToOffset({ animated: false, offset: 0 });
        }
    };

    scrollToLeft = () => {
        if (this._scrollView) {
            this._scrollView.getNode().scrollTo({x: 0, y: 0, animated: false});
        }
    };

    render() {
        return (
            <Animated.ScrollView
                ref={(ref: any) => this._scrollView = ref}
                style={styles.fill}
                horizontal={true}
                removeClippedSubviews={true}
                showsHorizontalScrollIndicator={false}
                scrollEventThrottle={1}
                onScroll={Animated.event(
                    [{nativeEvent: {contentOffset: {x: this.state.scrollX}}}],
                    {useNativeDriver: true},
                )}
            >
                <FlatList
                    ref={(ref: any) => this._flatList = ref}
                    removeClippedSubviews={true}
                    showsVerticalScrollIndicator={false}
                    data={this.props.data}
                    renderItem={this.renderRow}
                    keyExtractor={(item, index) => 'item_' + index}
                    stickyHeaderIndices={[0]}
                    ListHeaderComponent={this.renderHeader}
                />
            </Animated.ScrollView>
        );
    }

    renderHeader = () => {
        return (
            <View style={[styles.cellContainer, {backgroundColor: ColorConfig.PRIMARY_90}]}>
                <View style={styles.normalCellContainer}>
                    {
                        this.props.normalColumns.map((config, indexConfig) => {
                            return this.renderCell(
                                indexConfig,
                                this.props.normalColumns[indexConfig].width,
                                this.props.normalColumns[indexConfig].name,
                                this.props.normalColumns[indexConfig].visible,
                            );
                        })
                    }
                </View>
                <Animated.View style={[
                    styles.collapseCellContainer,
                    {
                        position: 'absolute',
                        transform: [{translateX: this._headerTranslate}],
                        backgroundColor: ColorConfig.PRIMARY_90,
                    },
                ]}>
                    {
                        this.props.collapseColumns.map((config, indexConfig) => {
                            return this.renderCell(
                                indexConfig,
                                this.props.collapseColumns[indexConfig].width,
                                this.props.collapseColumns[indexConfig].name,
                                this.props.collapseColumns[indexConfig].visible,
                            );
                        })
                    }
                </Animated.View>
            </View>
        );
    };

    renderRow = ({item, index}: { item: any, index: number }) => {
        return (
            <View key={index} style={styles.cellContainer}>
                <View style={styles.normalCellContainer}>
                    {
                        this.props.normalColumns.map((config, indexConfig) => {
                            return this.renderCell(
                                indexConfig,
                                this.props.normalColumns[indexConfig].width,
                                item[this.props.normalColumns[indexConfig].accessName],
                                this.props.normalColumns[indexConfig].visible,
                            );
                        })
                    }
                </View>
                <Animated.View style={[
                    styles.collapseCellContainer,
                    {
                        position: 'absolute',
                        transform: [{translateX: this._headerTranslate}],
                        backgroundColor: ColorConfig.PRIMARY_97
                    },
                ]}>
                    {
                        this.props.collapseColumns.map((config, indexConfig) => {
                            return this.renderCell(
                                indexConfig,
                                this.props.collapseColumns[indexConfig].width,
                                item[this.props.collapseColumns[indexConfig].accessName],
                                this.props.collapseColumns[indexConfig].visible,
                            );
                        })
                    }
                </Animated.View>
            </View>
        );
    };

    renderCell = (index: number, width: number, text: string, visible: boolean) => {
        return (
            <View key={index} style={[styles.cell, {width: width, opacity: visible ? 1 : 0}]}>
                <Text style={styles.cellText}>{text}</Text>
            </View>
        );
    };
}

const styles = StyleSheet.create({
    fill: {
        flex: 1,
    },

    // Header

    cellContainer: {
        overflow: 'hidden',
    },
    normalCellContainer: {
        flexDirection: 'row',
    },
    collapseCellContainer: {
        flexDirection: 'row',
    },
    cell: {
        paddingTop: 8 * UIConfig.RATIO,
        paddingBottom: 8 * UIConfig.RATIO,
        paddingLeft: 8 * UIConfig.RATIO,
        paddingRight: 8 * UIConfig.RATIO,

        borderRightColor: ColorConfig.PRIMARY_ALPHA_10,
        borderRightWidth: UIConfig.RATIO,
        borderBottomColor: ColorConfig.PRIMARY_ALPHA_10,
        borderBottomWidth: UIConfig.RATIO,

        justifyContent: 'center',
        alignItems: 'center',
    },
    cellText: {
        textAlign: 'center',
        color: ColorConfig.PRIMARY,
        fontSize: 14 * UIConfig.RATIO,
    }
});

export default CollapseTable;

希望这个答案可以帮助您像对我一样!