Nguyễn Hữu Hiếu

Posted on

## Problem

• Need to show more, expandable, calculate view before see it on view

## Solution

• Step 1: calculate item before animate it

• set position to absolute.
• set opacity to 0.
• set measured=1 and cache it
• Step 2: use react-native-animatable to animate item

``````import * as Animatable from 'react-native-animatable';
import React, {useState} from 'react';
import {Pressable, Text, TextStyle, View, ViewStyle} from 'react-native';

export const ShowMoreDemo = () => {
return (
<View>
<Text>Parent Content 1</Text>
<ShowMore>
<Text>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam rem
ducimus sit ipsa eligendi, beatae tempora ullam obcaecati at ab
consectetur ea eveniet labore non quod fugiat itaque facilis fuga?
</Text>
</ShowMore>
<Text>Parent Content 2</Text>
</View>
);
};

const ShowMore: React.FC = ({children}) => {
// const minHeight = 300;
const [isShowMore, setIsShowMore] = useState(false);
const [measured, setMeasured] = useState(false);
const [contentHeight, setContentHeight] = useState(0);

const [contentStyle, setContentStyle] = useState<ViewStyle>({
opacity: 0,
position: 'absolute',
});

console.log('measured', measured, contentHeight);

return (
<>
<View
style={contentStyle}
onLayout={e => {
if (!measured) {
setContentHeight(e.nativeEvent.layout.height);
setMeasured(true);
}
}}>
{!measured ? (
children
) : (
<Animatable.View
style={
{
backgroundColor: 'red',
height: isShowMore ? contentHeight : 0,
opacity: isShowMore ? 1 : 0,
} as ViewStyle
}
duration={300}
transition={['height', 'opacity']}>
{children}
</Animatable.View>
)}
</View>
<Pressable
style={
{
height: 48,
justifyContent: 'center',
alignItems: 'center',
} as ViewStyle
}
onPress={() => {
setIsShowMore(!isShowMore);
setContentStyle({
opacity: 1,
position: 'relative',
});
}}>
<Text
style={
{
color: '#000',
fontSize: 12,
fontWeight: 'bold',
} as TextStyle
}>