oblador / react-native-collapsible

Animated collapsible component for React Native, good for accordions, toggles etc
MIT License
2.44k stars 452 forks source link

How to get expended height of the accordion #150

Open vijay-dadhich09 opened 6 years ago

vijay-dadhich09 commented 6 years ago

Hi How can i get expended height of the accordion when tap on the header. I am trying to get using onChange but it only return index.

JoseVf commented 6 years ago

You can put the Accordion component inside a ScrollView and capture the ScrollView's onContentSizeChange event to get the full height of your Accordion.

i.e:

<ScrollView onContentSizeChange={(width, height) => console.log(width, height)}>
  <Accordion
    activeSection={this.state.activeSection}
    sections={this.props.sections}
    renderHeader={this._renderHeader}
    renderContent={this._renderContent}
  />
</ScrollView>

When the activeSection changes (show/hide content) it fires the onContentSizeChange where you can get the width and height of your Accordion.

iRoachie commented 6 years ago

Hey @vijay-dadhich09 sorry for late follow up. What's your use case for this behavior? What are you trying to achieve by getting the expanded height?

vijay-dadhich09 commented 6 years ago

Hi iRoachie thanks for the reply. Actually, I have number of accordions in a scrollview component and the requirement is to scroll up bottom positions accordions after expend because when user clicks on the bottom accordion the expended area not showing in the scroll view that need to scroll up according to expended height. So, I think I need two things one is expended height and other things is current y position of the clicked accordion. If I can get both of the values then I can build my logic to scroll up scrollView. Hope you get the requirement.

JoseVf commented 6 years ago

Maybe dupe of #86?

vijay-dadhich09 commented 6 years ago

Ho sir #86? is not related to my issue. I make it thinks more simple. How to ScrollToTop expended accordion. As soon as expend a accordion it move to top of the scrollView.

iRoachie commented 6 years ago

Sorry for late reply, Does @JoseVf solution work for you?

ramnaq commented 6 years ago

Hi, @iRoachie! I think I have the same problem as @vijay-dadhich09, so I could say that #86 is not a solution. An example: We have an Accordion with 5 sections. The 4th section, in fact, is an Accordion itself. In this case, when we expand a section of this last accordion, some content doesn't appear. I think that it happends because the sections of the secondary accordion is hiden under the 5th section, which doesn't move down.

How we can see, in the third image bellow, SIGNATURE 2 disappears (by the way there is more content to show when tapping SIGNATURE 1)

(first view) tap0

(showing sections of the 4th section accordion) tap1

(some content disappears "under" the next section of the outer accordion) tap2

gilshaan commented 5 years ago

Use flatlist inside accordion to solve the issue. Flatlist will automatically generate scroll view when new content is added to it..

If you need full height of a flat list inside accordion view then you have to re-render the accordion view.Using accordion with react-native-collapsible will not dynamically change its content height.Insted a scroll view will appear.I solved it by setting a flag and re-rendering the view of accordion.

This is my flatlist. <FlatList data={section.content} renderItem={this.renderItem} extraData={this.state.refresh} ListEmptyComponent={this.ListEmptyView} /> I re-rendered my accordion view like this when i add new content to flatlist. {this.state.refresh ? ( <View style={styles.flatlistMainContainer}> <Accordion sections={this.state.accordionArray} activeSections={this.state.activeSections} renderHeader={this.renderAccordionHeader} renderContent={this.renderAccordionItem} onChange={this._updateSections} touchableComponent={TouchableOpacity} /> </View> ) : null}

When i make any change in its content dynamically i will set the flag as : this.setState({ refresh: false }, () => { this.setState({ refresh: true }); });

By doing like this component refresh its content height.

Aravinth-2020 commented 1 week ago

`import React, { useEffect, useRef, useState } from 'react'; import { Animated, ScrollView, StyleSheet, View } from 'react-native'; import { Text } from 'react-native-paper'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; import { TouchableOpacity } from 'react-native'; import theme from '../../styles/theme';

type Props = { title: string; count: number; isExpanded: boolean; onToggle: () => void; renderBadge: (value: number) => React.ReactNode; children: React.ReactNode; };

const Accordion = ({ title, count, children, renderBadge, isExpanded, onToggle }: Props) => { const [collapsableHeight, setCollapsableHeight] = useState(0); const animatedController = useRef(new Animated.Value(0)).current;

const bodyHeight = animatedController.interpolate({
    inputRange: [0, 1],
    outputRange: [0, collapsableHeight],
});

const handleOnContentSizeChange = (width: number, height: number) => {
    setCollapsableHeight(height);
};

useEffect(() => {
    Animated.timing(animatedController, {
        duration: 400,
        toValue: isExpanded ? 1 : 0,
        useNativeDriver: false,
    }).start();
}, [isExpanded]);

return (
    <View>
        <View style={styles.container}>
            <TouchableOpacity activeOpacity={0.7} onPress={onToggle} style={styles.header}>
                <View style={styles.headerContent}>
                    {renderBadge(count)}
                    <Text style={styles.title}>{title}</Text>
                </View>
                <MaterialCommunityIcons
                    name={isExpanded ? "chevron-up" : "chevron-down"}
                    size={24}
                    color="#1976D2"
                />
            </TouchableOpacity>
        </View>
        <Animated.View style={[styles.body, { maxHeight: bodyHeight }]}>
            <ScrollView onContentSizeChange={handleOnContentSizeChange}>
                {children}
            </ScrollView>
        </Animated.View>
    </View>
);

};

const styles = StyleSheet.create({ container: { borderBottomWidth: 1, borderColor: 'lightgray', marginRight: 16, marginLeft: 16, }, header: { minHeight: 41, backgroundColor: 'white', borderRadius: 4, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, headerContent: { flexDirection: 'row', alignItems: 'center', }, title: { fontSize: 14, fontWeight: '600', fontFamily: theme.Roboto }, count: { fontSize: 18, fontWeight: '500', marginLeft: 10, }, body: { backgroundColor: 'white', borderRadius: 4, overflow: 'hidden', }, });

export default Accordion; `

This is my custom animated Accordion. Please use this to avoid third party integration 😎