美文网首页Android开发经验谈RN
React-Native 版高仿淘宝、京东商城首页、商品分类页面

React-Native 版高仿淘宝、京东商城首页、商品分类页面

作者: 飞鱼_9d08 | 来源:发表于2020-10-10 23:09 被阅读0次

    正在做商城项目的同学有福啦,看看是你们想要的效果吗?

    项目地址:https://github.com/pengzhenjin/react-native-mall

    效果图

    已实现功能

    沉浸式状态栏
    酷炫的顶部导航动画
    消息角标
    循环轮播图
    搜索
    商品一级分类
    商品二级分类
    商品子分类
    顶部滑动的tab、智能下拉菜单
    用到的技术
    自定义 Badge(角标)
    动画、动画插值器
    Swiper 轮播图
    自定义 tab
    自定义 popup 弹窗下拉菜单
    FlatList、SectionList
    重点代码解析

    MallHome.js

    /**
         * 滚动条监听事件
         * @param event
         */
        onScrollFunc = (event) => {
            // 将滚动的值绑定到渐变动画
            Animated.event([{nativeEvent: {contentOffset: {y: this.state.logoOpacity}}}])(event)
     
            // 将滚动的值绑定到边距动画
            Animated.event([{nativeEvent: {contentOffset: {y: this.state.searchViewMargin}}}])(event)
        }
    
    renderSearchView = () => {
            const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity)
     
            const marginRight = this.state.searchViewMargin.interpolate({
                inputRange: [0, 80], // 当滚动条滚动到0~80的位置时
                outputRange: [0, 80], // 将右边距改为从0~80
                extrapolate: 'clamp' // 滚动超出0~80的范围,不在更改边距
            })
            const marginTop = this.state.searchViewMargin.interpolate({
                inputRange: [0, 160], // 当滚动条滚动到0~160的位置时
                outputRange: [0, -36], // 将上边距改为从0~-36
                extrapolate: 'clamp' // 滚动超出0~160的范围,不在更改边距
            })
     
            return (
                <AnimatedTouchableOpacity
                    style={styles.top_search_container(marginRight, marginTop)}
                    activeOpacity={0.8}
                    onPress={this.gotoSearch}
                >
                    <Image style={styles.top_search_icon} source={iconSearch} />
                    <Text style={styles.top_search_text}>{'新品'}</Text>
                </AnimatedTouchableOpacity>
            )
        }
    

    GoodsCategory.js 解析

    render() {
            return (
                <View style={styles.container}>
                    <View style={styles.first_category_container}>
                // 一级分类列表,采用FlatList
                        <FlatList
                            ref={refs => this.flatList = refs}
                            keyExtractor={(item, index) => index.toString()}
                            data={this.state.firstCategoryData}
                            renderItem={this.renderFirstCategoryItem}
                            ItemSeparatorComponent={this.renderSeparatorLine}
                        />
                    </View>
                    <View style={styles.second_category_container}>
                // 二级、三级分类列表,采用SectionList
                        <SectionList
                            ref={refs => this.sectionList = refs}
                            renderSectionHeader={this.renderSecondCategorySectionHeader}
                            renderItem={this.renderSecondCategoryItem}
                            sections={this.state.secondCategoryData}
                            ItemSeparatorComponent={null}
                            ListHeaderComponent={null}
                            ListFooterComponent={null}
                            keyExtractor={(item, index) => index + item}
                        />
                    </View>
                </View>
            );
        }
    
        // 点击一级分类时,需要计算滚动条的位置
        onClickFirstCategoryItem = (item, index) => {
            this.setState({selectedFirstCategoryIndex: index});
     
            // 计算当前 item 的高度
            const indexHeight = firstCategoryItemHeight * index;
     
            // 计算屏幕一半的高度
            const halfHeight = (height - 65) / 2;
     
            // 如果当前 item 的高度 大于 屏幕一半的高度,就让滚动条滚动 indexHeight - halfHeight 高度(类似京东商品分类效果)
            if (indexHeight > halfHeight) {
                this.flatList.scrollToOffset({
                    animated: true,
                    offset: indexHeight - halfHeight,
                });
            }
     
            this.sectionList.scrollToLocation({
                animated: true,
                itemIndex: 0,
                sectionIndex: 0,
            });
        };
    

    TopTabView.js 解析

        /**
         * 显示下拉菜单
         * @param index 当前选中时的 tab 下标
         */
        showDropdownMenu = (index) => {
            // measure方法测量"箭头图标"在页面中的位置、宽高
            this.arrowIcon.measure((x, y, width, height, pageX, pageY) => {
                const topOffset = pageY + height // 计算"下拉菜单"距离页面顶部的偏移量
                this.dropdownMenu.show(topOffset, index) // 显示"下拉菜单"
            })
        }
    

    组件的 measure((x, y, width, height, pageX, pageY) => {}) 方法可以动态的获取组件在屏幕中的位置、宽高信息。measure 方法的参数 x,y 表示组件的相对位置,width,height 表示组件的宽度和高度,pageX,pageY 表示组件相对于屏幕的绝对位置。

    TopDropdownMenu.js 解析

    // 使用 Modal 来实现弹窗菜单,达到遮罩效果
     render() {
            const {isVisible, data, topOffset} = this.state;
            return (
                <Modal
                    animationType="fade"
                    transparent={true}
                    onRequestClose={() => this.hide()}
                    visible={isVisible}
                >
                    <TouchableOpacity
                        style={styles.container}
                        activeOpacity={1}
                        onPress={() => this.hide()}
                    >
                        <FlatList
                            style={[styles.content_container, {top: topOffset}]}
                            keyExtractor={(item, index) => index.toString()}
                            data={data}
                            renderItem={this.renderItem}
                            horizontal={false}
                            numColumns={2}
                            renderSeparator={null}
                        />
                    </TouchableOpacity>
                </Modal>
            );
        }
    
    
        // 使用绝对布局和 top 来计算弹窗菜单的位置,其中 top 是动态计算的
        content_container: {
            position: 'absolute',
            top: 0,
            backgroundColor: '#FFFFFF',
        },
    

    Copyright: 采用 知识共享署名4.0 国际许可协议进行许可
    Links: https://www.pengzhenjin.top/archives/react-native版高仿淘宝京东商城首页商品分类页面

    最后

    本文在开源项目:https://github.com/xieyuliang/Note-Android中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中...

    相关文章

      网友评论

        本文标题:React-Native 版高仿淘宝、京东商城首页、商品分类页面

        本文链接:https://www.haomeiwen.com/subject/ptrspktx.html