Make animated collapsible card component, with initial props to show or hide
Made a brand new one for you. Simple and works fine.
Note: no state
required for this component. fewer state, better performance.
Maybe you could modify your own style on top of this =)
class Card extends Component {
anime = {
height: new Animated.Value(),
expanded: false,
contentHeight: 0,
}
constructor(props) {
super(props);
this._initContentHeight = this._initContentHeight.bind(this);
this.toggle = this.toggle.bind(this);
this.anime.expanded = props.expanded;
}
_initContentHeight(evt) {
if (this.anime.contentHeight>0) return;
this.anime.contentHeight = evt.nativeEvent.layout.height;
this.anime.height.setValue(this.anime.expanded ? this._getMaxValue() : this._getMinValue() );
}
_getMaxValue() { return this.anime.contentHeight };
_getMinValue() { return 0 };
toggle() {
Animated.timing(this.anime.height, {
toValue: this.anime.expanded ? this._getMinValue() : this._getMaxValue(),
duration: 300,
}).start();
this.anime.expanded = !this.anime.expanded;
}
render() {
return (
<View style={styles.titleContainer}>
<View style={styles.title}>
<TouchableHighlight underlayColor="transparent" onPress={this.toggle}>
<Text>{this.props.title}</Text>
</TouchableHighlight>
</View>
<Animated.View style={[styles.content, { height: this.anime.height }]} onLayout={this._initContentHeight}>
{this.props.children}
</Animated.View>
</View>
);
}
}
Usage:
<Card title='Customized Card 1' expanded={false}>
<Text>Hello, this is first line.</Text>
<Text>Hello, this is second line.</Text>
<Text>Hello, this is third line.</Text>
</Card>
Visual result: (only second card start with expanded={true}
, others with expanded={false}
)
Comments
-
wuno almost 2 years
Background
Using React Native I was able to make collapsible card component. On Icon click the card slides up hiding its content, or expands showing its content. I would think setting the default value would be as easy as setting expanded to false or true, but I think the problem here is that when it is toggled an animation is triggered which changes the height of the card.
Example
class CardCollapsible extends Component{ constructor(props){ super(props); this.state = { title: props.title, expanded: true, animation: new Animated.Value(), iconExpand: "keyboard-arrow-down", }; } _setMaxHeight(event){ this.setState({ maxHeight : event.nativeEvent.layout.height }); } _setMinHeight(event){ this.setState({ minHeight : event.nativeEvent.layout.height }); this.toggle = this.toggle.bind(this); } toggle(){ let initialValue = this.state.expanded? this.state.maxHeight + this.state.minHeight : this.state.minHeight, finalValue = this.state.expanded? this.state.minHeight : this.state.maxHeight + this.state.minHeight; this.setState({ expanded : !this.state.expanded }); if (this.state.iconExpand === "keyboard-arrow-up") { this.setState({ iconExpand : "keyboard-arrow-down" }) } else { this.setState({ iconExpand : "keyboard-arrow-up" }) } this.state.animation.setValue(initialValue); Animated.spring( this.state.animation, { toValue: finalValue } ).start(); } render(){ return ( <Animated.View style={[styles.container,{height: this.state.animation}]}> <View style={styles.titleContainer} onLayout={this._setMinHeight.bind(this)}> <CardTitle>{this.state.title}</CardTitle> <TouchableHighlight style={styles.button} onPress={this.toggle} underlayColor="#f1f1f1"> <Icon name={this.state.iconExpand} style={{ fontSize: 30 }}/> </TouchableHighlight> </View> <Separator /> <View style={styles.card} onLayout={this._setMaxHeight.bind(this)}> {this.props.children} </View> </Animated.View> ); } } var styles = StyleSheet.create({ container: { backgroundColor: '#fff', margin:10, overflow:'hidden' }, titleContainer: { flexDirection: 'row' }, card: { padding: 10 } }); export { CardCollapsible };
Open
Closed
Question
My goal is to allow a person calling the component to set the initial state of the component to expanded or open. But when I try changing the expanded state to
false
it does not render closed.How would I go about allowing the user calling the component to select whether it is expanded or closed on initial component render?