首页 > 解决方案 > 在 React Native 中使用 Collapsible 创建手风琴

问题描述

我创建了一个手风琴,并为它创建了一些逻辑,但是当我查看我的代码时感觉不对。我不知道在哪里问所以我在这里问。

所以我创建了一个手风琴组件并在我的屏幕上实现了它。这款手风琴的特别之处在于,当一个手风琴打开时,另一个手风琴关闭。所以我用useState()我转发作为手风琴的道具。我也想把useState()手风琴放进去,但是当我点击另一个手风琴时,我不知道如何关闭它。所以我创造了这个。

我需要有关如何改进它或如何使其更清洁的提示,因为现在当我查看代码时它可以工作但看起来并不好。

//AccordionCompontent.js
import React from 'react'
import { StyleSheet, View, Text, Dimensions } from 'react-native';
import Collapsible from 'react-native-collapsible';
import { TouchableWithoutFeedback } from 'react-native-gesture-handler';

const Accordion = props => {


    return (
        <View>
            <TouchableWithoutFeedback onPress={props.onPress}>
            <View style={styles.accordionContainer}>
            <Text style={styles.accordionContainerTitle} >{props.title}</Text>
            </View>
            </TouchableWithoutFeedback>
            <Collapsible style={styles.accordionCollapsedContainer} collapsed={props.isCollapsed}>
                {props.accordionRender}
            </Collapsible>
        </View>
    );
}

export default Accordion;

const styles = StyleSheet.create({
    accordionContainer: {
        justifyContent:'center',
        borderBottomWidth: 1,
        borderBottomColor: '#fff',
       minHeight: Dimensions.get('window').height / 15
    },
    accordionCollapsedContainer: {
        borderBottomWidth: 1,
        borderBottomColor: '#fff'
    },
    accordionContainerTitle: {
        color: '#fff',
        fontSize: 16,
        marginLeft:10
    },

})
//InformationScreen.js
import React, { useCallback, useLayoutEffect, useState } from 'react'
import { Text, View, StyleSheet, TouchableWithoutFeedback } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons'
import BodyText from '../components/Atomic/BodyText';
import Accordion from '../components/Accordion/Accordion';


const InformationScreen = props => {

    const [isCollapsed, setIsCollapsed] = useState([true, true, true, true, true])

    const collapse = (id) => {
        let updatetIsCollapsed = [...isCollapsed]
        updatetIsCollapsed[id] = !updatetIsCollapsed[id]
        const filteredUpdateIsCollapse = updatetIsCollapsed.filter((value, index) => id !== index)
        filteredUpdateIsCollapse.forEach(element => {
            if (!element) {
                const index = filteredUpdateIsCollapse.indexOf(element)
                filteredUpdateIsCollapse[index] = true
            }
        });
        filteredUpdateIsCollapse.splice(id, 0, updatetIsCollapsed[id])
        setIsCollapsed(filteredUpdateIsCollapse)
    }


    useLayoutEffect(() => {
        props.navigation.setOptions({
            title: 'Information',
            headerStyle: {
                backgroundColor: '#000'
            },
            headerTitleStyle: {
                fontSize: 22,
                color: '#fff'
            },
            headerLeft: () => (
                <View></View>
            ),
            headerRight: () => (
                <TouchableWithoutFeedback onPress={() => {
                    props.navigation.popToTop()
                }}>
                    <View style={styles.iconContainer}>
                        <Icon name="home" size={30} color={'#fff'} />
                    </View>
                </TouchableWithoutFeedback>
            )
        })
    })
    return (
        <View style={styles.container}>

            <Accordion onPress={useCallback(() => {
                collapse(0)
            },
                [isCollapsed, setIsCollapsed],
            )} title={"Lorem"} isCollapsed={isCollapsed[0]} accordionRender={
                <View style={styles.accordionItemContainer}>
                    <View style={styles.accordionItemSpacing}>
                        <BodyText>Lorem Ipsum</BodyText>
                        <BodyText>Lorem Ipsum</BodyText>
                    </View>
                    <View>
                        <BodyText>Lorem ipsum</BodyText>
                        <BodyText>Lorem ipsum</BodyText>
                    </View>
                </View>
            } />
            <Accordion onPress={useCallback(() => {
                collapse(1)
            },
                [isCollapsed, setIsCollapsed],
            )} title={"Bla bla"} isCollapsed={isCollapsed[1]} accordionRender={
                <View>
                    <Text>Test</Text>
                    <Text>Test</Text>
                </View>
            } />
            <Accordion onPress={useCallback(() => {
                collapse(2)
            },
                [isCollapsed, setIsCollapsed],
            )} title={"Bla bla"} isCollapsed={isCollapsed[2]} accordionRender={
                <View>
                    <Text>Test</Text>
                    <Text>Test</Text>
                </View>
            } />
            <Accordion onPress={useCallback(() => {
                collapse(3)
            },
                [isCollapsed, setIsCollapsed],
            )} title={"Bla bla"} isCollapsed={isCollapsed[3]} accordionRender={
                <View>
                    <Text>Test</Text>
                    <Text>Test</Text>
                </View>
            } />
            <Accordion onPress={useCallback(() => {
                collapse(4)
            },
                [isCollapsed, setIsCollapsed],
            )} title={"Lorem Ipsum"} isCollapsed={isCollapsed[4]} accordionRender={
                <View style={styles.accordionItemContainer}>
                     <View style={styles.accordionItemSpacing}>
                        <BodyText>Lorem Ipsum</BodyText>
                        <BodyText>Lorem Ipsum</BodyText>
                    </View>
                    <View>
                        <BodyText>Lorem ipsum</BodyText>
                        <BodyText>Lorem ipsum</BodyText>
                    </View>
                </View>
            } />

        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        backgroundColor: '#000',
        flex: 1,
        borderTopWidth: 2,
        borderTopColor: '#fff'
    }
    ,
    iconContainer: {
        height: 50,
        width: 50,
        borderLeftWidth: 2,
        borderLeftColor: '#fff',
        overflow: 'hidden',
        justifyContent: 'center',
        alignItems: 'flex-end'
    },
    accordionContainerTitle: {
        color: '#000',
        fontSize: 16,
    },
    accordionItemContainer: {
        paddingVertical: 10,
    },
    accordionItemText: {
        color: '#000',
        fontSize: 16,
        marginHorizontal: 10,
    },
    accordionItemSpacing: {
        marginBottom: 10
    }
})

export default InformationScreen;

标签: javascriptreactjsreact-nativereact-hooksuse-state

解决方案


  1. 取下挂钩。JSX/多伦多证券交易所
  2. 按功能生成手风琴
  3. 使用地图索引道具来切换手风琴
import React, { useCallback, useLayoutEffect, useState } from 'react'
import { Text, View, StyleSheet, TouchableWithoutFeedback } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons'
import BodyText from '../components/Atomic/BodyText';
import Accordion from '../components/Accordion/Accordion';


const getaccordianItems = () => ([

                        <View style={styles.accordionItemSpacing}>
                            <BodyText>Lorem Ipsum</BodyText>
                            <BodyText>Lorem Ipsum</BodyText>
                        </View>
                        <View>
                            <BodyText>Lorem ipsum</BodyText>
                            <BodyText>Lorem ipsum</BodyText>
                        </View>,

<View>
                    <Text>Test</Text>
                    <Text>Test</Text>
                </View>,

<View>
                    <Text>Test</Text>
                    <Text>Test</Text>
                </View>,

<View>
                    <Text>Test</Text>
                    <Text>Test</Text>
                </View>,

<View>
                    <Text>Test</Text>
                    <Text>Test</Text>
                </View>

])

const InformationScreen = props => {

    
        const [isExpandedIndex, setIsExpanded] = useState();
    
        useLayoutEffect(() => {
            props.navigation.setOptions({
                title: 'Information',
                headerStyle: {
                    backgroundColor: '#000'
                },
                headerTitleStyle: {
                    fontSize: 22,
                    color: '#fff'
                },
                headerLeft: () => (
                    <View></View>
                ),
                headerRight: () => (
                    <TouchableWithoutFeedback onPress={() => {
                        props.navigation.popToTop()
                    }}>
                        <View style={styles.iconContainer}>
                            <Icon name="home" size={30} color={'#fff'} />
                        </View>
                    </TouchableWithoutFeedback>
                )
            })
        })
        return (
            <View style={styles.container}>
                {accordionList.map((item,index)=>(
                <Accordion onPress={()=> { setIsExpanded(index) }} title={"Lorem"} isCollapsed={isExpanded !== index} accordionRender={
                    <View style={styles.accordionItemContainer}>
                        {item}
                    </View>
                  } />
                )}
    
            </View>
        );
    }
    
    const styles = StyleSheet.create({
        container: {
            backgroundColor: '#000',
            flex: 1,
            borderTopWidth: 2,
            borderTopColor: '#fff'
        }
        ,
        iconContainer: {
            height: 50,
            width: 50,
            borderLeftWidth: 2,
            borderLeftColor: '#fff',
            overflow: 'hidden',
            justifyContent: 'center',
            alignItems: 'flex-end'
        },
        accordionContainerTitle: {
            color: '#000',
            fontSize: 16,
        },
        accordionItemContainer: {
            paddingVertical: 10,
        },
        accordionItemText: {
            color: '#000',
            fontSize: 16,
            marginHorizontal: 10,
        },
        accordionItemSpacing: {
            marginBottom: 10
        }
    })
    
    export default InformationScreen;


推荐阅读