繁体   English   中英

在 React Native 中使用 Collapsible 创建手风琴

[英]Creating an Accordion in React Native with 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;
  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;

好的,在Michael Bahl的帮助下,我能够编写一些更好的代码。 他的代码很好,但我对它做了一些调整。 现在一切正常,我可以把我需要的所有东西放在我的手风琴里。

我对accordionCompontent.js 进行了一个小改动,在屏幕上,我应用了Michael 展示的代码,并进行了一些小调整,使其对我来说更加灵活。

//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} 
             //The small change is at collapsed
             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
    },

})
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 getAccordionItems = (version, expiresDate, scriptSize, packageSize) => ([
    ['General Information',
        <View>
            <View style={styles.accordionItemSpacing}>
                <BodyText>Version {version}</BodyText>
                <BodyText>License expires on {expiresDate}</BodyText>
            </View>
            <View>
                <BodyText>Size of scripts folder: {scriptSize} MB</BodyText>
                <BodyText>Size of packages folder: {packageSize} MB</BodyText>
            </View>
        </View>],

    ['lorem',
        <View>
            <View style={styles.accordionItemSpacing}>
                <BodyText>Lorem Ipsum</BodyText>
                <BodyText>Lorem Ipsum</BodyText>
            </View>
            <View>
                <BodyText>Lorem ipsum</BodyText>
                <BodyText>Lorem ipsum</BodyText>
            </View>
        </View>],
    ['lorem',
        <View>
            <View style={styles.accordionItemSpacing}>
                <BodyText>Lorem Ipsum</BodyText>
                <BodyText>Lorem Ipsum</BodyText>
            </View>
            <View>
                <BodyText>Lorem ipsum</BodyText>
                <BodyText>Lorem ipsum</BodyText>
            </View>
        </View>],
])

const InformationScreen = props => {
    const accordionList = getAccordionItems('1.0', '2021/10/20', 1.00, 0.00)

    const [isExpanded, 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>
            )
        })
    })

    accordionList.map((item, index) => {
        console.log(item)
        console.log(index)
    })
    return (
        <View style={styles.container}>
            {accordionList.map((item, index) => (
                <Accordion onPress={() => { 
                    if (isExpanded === index){
                        setIsExpanded(accordionList.size)
                    } else{
                    setIsExpanded(index) 
                    }
            }} title={item[0]} isCollapsed={isExpanded === index} accordionRender={
                    <View style={styles.accordionItemContainer}>
                        {item[1]}
                    </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: '#fff',
        fontSize: 16,
    },
    accordionItemContainer: {
        paddingVertical: 10,
    },
    accordionItemText: {
        color:'#fff',
        fontSize: 16,
        marginHorizontal: 10,
    },
    accordionItemSpacing: {
        marginBottom: 10
    }
})

export default InformationScreen;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM