생각은 길게 코딩은 짧게

[React-Native] Animated View 본문

React Native

[React-Native] Animated View

sayhee 2023. 1. 26. 19:04
728x90

Animated.View를 사용하여 구현해보았습니당


✅ Animated 기준값을 전역변수로 지정

constructor(props) {
        super(props);
        this.AnimatedHeaderValue = new Animated.Value(0); // Animated 기준값(0,0)  
        this.state = {
            goodsContent: [],
            indicator : false,
        };
}

 

✅ render 부분에 Animated.View 사용

render() {
        const Header_Maximum_Height = 120;
        const Header_Minimum_Height = 60;

        const renderHeader = this.AnimatedHeaderValue.interpolate(
            {
                inputRange: [0, Header_Maximum_Height],
                outputRange: [0, -Header_Maximum_Height],
            });

        const renderSearchBar = this.AnimatedHeaderValue.interpolate(
            {
                inputRange: [0, Header_Maximum_Height],
                outputRange: [Header_Maximum_Height, 0],
                extrapolate: 'clamp'
            });

        return (
            <>
                <View style={{ flex: 1 }}>
                    <FlatList
                        style={styles.goodsContent}
                        data={this.state.goodsContent}
                        renderItem={({ item , index }) => <ListItem index={index} item={item} id={item.id} navigation={this.props.navigation} />}
                        refreshing={this.state.refreshing} //새로고침
                        onRefresh={this.handleRefresh}
                        scrollEventThrottle={16}
                        contentContainerStyle={{ paddingTop: Header_Maximum_Height + Header_Minimum_Height+30 }}
                        onScroll={Animated.event(
                            [{ nativeEvent: { contentOffset: { y: this.AnimatedHeaderValue } } }],
                            { useNativeDriver: false })}
                    />
                    
                    <Animated.View style={[styles.homeTop, { transform: [{ translateY: renderHeader }] }]}>
                        <ImageBackground source={require('../../../images/background/main-background/main-background.png')} style={{ width: "100%", height: "100%" }}>
                            <View style={styles.title}>
                                <View style={styles.titleRow}>
                                    <Text style={[styles.titleText, styles.titleBoldText]}>
                                        손 쉽게 검색
                                    </Text>
                                    ...
                            </View>
                        </ImageBackground>
                    </Animated.View>

                    <Animated.View style={[styles.searchBarStyle, { height: Header_Minimum_Height, transform: [{ translateY: renderSearchBar }] }]}>
                        <ImageBackground source={require('../../../images/background/main-background/main-background.png')} style={{ width: "100%", height: "100%", flexDirection: 'row' }}>
                            <TextInput
                                onChange={(value) => this.search(value.nativeEvent.text)}
                                placeholder="품명을 입력해주세요"
                                placeholderTextColor="light grey"
                                style={styles.input}
                                value={this.state.number}
                            />
                            {/* 카메라로 검색 */}
                            <TouchableOpacity
                                style={styles.cameraSearchButton}
                                onPress={this.goCameraButtonClicked}>
                                <Image
                                    source={require('../../../images/icon/camera-icon/camera-icon.png')}
                                />
                            </TouchableOpacity>
                        </ImageBackground>
                        ...
                    </Animated.View>
                </View>
            </>
        );
    }

Header_Maximum_Height 는 검색 부분 위의 Header 부분의 높이

Header_Minimum_Height 는 검색 부분의 높이

 

renderSearchBar에 exrtapolate를 clamp로 주었습니다.

 

📍 clamp는 interpolate에서 Animated value가 inputRage의 범위를 벗어났을 때

outputRage의 최대(또는 최소) 값을 반환합니다.

즉, inputRange안에서의 값만 변화가 있고 Animated Value가 inputRange를 벗어나면 변화가 없습니다.

따라서 renderSearchBar만 남을 수 있게 되는 것이죠!

 

💡 extrapolate를 주지 않았을 경우