React-Native 城市列表(仿美团)

项目需要写了一个城市列表的界面,供有需要的人参考一下

功能

点击右侧导航滚动到响应位置

导航跳转.gif

提供搜索功能

搜索功能.gif

说明

简单介绍

我使用的FlatList。一开始也尝试使用SectionList,但是在尝试执行跳转时发现位置不好计算,而且感觉SectionList的效率并不如FlatList 所以就使用FlatList 了。

                  <FlatList 
                        ref = {'FlatList'}
                        style={{width:'100%'}}
                        data={this.state.sections}
                        contentContainerStyle = {styles.list}
                        showsVerticalScrollIndicator = {false}
                        renderItem = {this._renderItem}
                        initialNumToRender = {50}
                        getItemLayout={(data, index) =>this._getItemLayout(data,index)}
                        keyExtractor={(item,index)=>{
                            return(index.toString());
                        }}
                   >
                   </FlatList> 

这样看很简单吧。
数据的初始化是在componentDidMount 中完成的
数据来源是从其他人的代码中找到的json文件。
另外因为要加入,定位城市,常用城市,热门城市,所以变成了下面的样子。

componentDidMount(){
        let cityContent2 = cityContent.data;
        let letterList = [];              // 侧边的导航数据
        let cityArray = [];
        let sections = [];              // 最后将所以的信息放入其中
        this.city2number = 0;
        this.descNumber = 0;
        this.titleCityArray = [0];

        sections[sections.length] = {
            name:'定位城市',
            type:'desc',
        };

        sections[sections.length] = {
            name:'珠海',
            type:'location',
        };
        sections[sections.length] = {
            name:'常用城市',
            type:'desc',
        };
        //在定位城市和热门城市中设置 三个城市是一个组。
        // 不然不好实现将他们放在一行中的操作。使用flexWrap 也能实现,但是会导致计算起来麻烦
       //设置不同的type 在 FlatList 中的 renderItem 中用于区分,实现不同的样式
        sections[sections.length] = {
            name:'珠海,广州',
            type:'city2',
        };

        sections[sections.length] = {
            name:'热门城市',
            type:'desc',
        };

        sections[sections.length] = {
            name:'珠海,广州,杭州',
            type:'city2',
        };
        sections[sections.length] = {
            name:'北京,上海,西安',
            type:'city2',
        };
        sections[sections.length] = {
            name:'广州,杭州,北京',
            type:'city2',
        };
        sections[sections.length] = {
            name:'上海,西安',
            type:'city2',
        };
        letterList.splice(0,0,'定位','常用','热门');
       
      
        sections.forEach(element => {
            if(element.type != 'desc'){
                this.city2number++;
            }else{
                this.descNumber++;
            }
        });
        let i = 0;
        cityContent2.forEach(element => {
            sections[sections.length] = {
                name:element.title,
                type:'letter',
            };
            element.city.forEach(element => {
                if(element.city_child == element.city_parent){
                    sections[sections.length] = {
                        name:element.city_child,
                        type:'city',
                    }
                    i++;
                }
            });
            this.titleCityArray[this.titleCityArray.length] = i;
            letterList[letterList.length] = element.title;
        });
        
        


     // 查找时使用的数据
        let key = 0;
        cityArray = [];
        cityContent2.forEach(element => {
            element.city.forEach(element => {
                if(element.city_child == element.city_parent){
                cityArray[cityArray.length] = {
                    'name':element.city_child,
                    'name_en':element.city_child_en,
                    'key':key++,
                }
                }
            });
        });
        this.setState({
          sections:sections,
          listData:letterList,
          cityBase:cityArray,
          searchArray:cityArray,
        });
    
    }

下面是_renderItem 根据不同的type 返回不同的样式。

_renderItem = (info) => {
        var txt = '  ' + info.item.name;
        switch(info.item.type){
            case 'city':{
                return( 
                    <Text
                        style={{ 
                            height: CITYHEIGHT,
                            width:Utils.size.width-70,
                            textAlignVertical: 'center', 
                           // backgroundColor: "#ffffff", 
                            color: '#5C5C5C', 
                            fontSize: 15,
                            borderBottomColor:'rgb(161,161,161)',
                            borderBottomWidth:1, 
                            }}
                        >
                        {txt}
                    </Text>
                )
            }
            case 'letter':{
                return(
                    <Text
                        style={{ 
                            height: TITLEHEIGHT,
                            width:Utils.size.width-70,
                            textAlignVertical: 'center', 
                            //backgroundColor: "#0f0", 
                            color: '#5C5C5C', 
                            fontSize: 15,
                            borderBottomColor:'rgb(161,161,161)',
                            borderBottomWidth:1, 
                            }}
                        >
                        {txt}
                    </Text>
                )
            }
            case 'desc':{
                return(
                    <Text
                        style={{ 
                            height: DESCHEIGHT,
                            width:Utils.size.width-50,
                            textAlignVertical: 'center', 
                            //backgroundColor: "#0f0", 
                            color: '#5C5C5C', 
                            fontSize: 15,
                            }}
                        >
                        {txt}
                    </Text>
                )
            }
            case 'city2':{
                txt = txt.split(',');
                return(
                    <View style={{
                        flexDirection:'row',
                    }}>
                        {
                            txt.map((element,index) => {
                                return <Text
                                    key={'info'+info.index+'index'+index}
                                    style={{ 
                                    textAlignVertical: 'center', 
                                    textAlign:'center',
                                    width:94.5,
                                    height:CITYHEIGHT2,
                                    borderColor:'rgb(220,220,220)',
                                    borderWidth:Utils.pixel,
                                    fontSize: 15 ,
                                    marginRight:14,
                                }}>
                                    {element}
                                </Text>
                            })
                        }
                    </View>
                    )
            }
            case 'location':{
                return(
                    <Text
                        style={{ 
                        textAlignVertical: 'center', 
                        textAlign:'center',
                        width:94.5,
                        height:CITYHEIGHT2,
                        borderColor:'rgb(220,220,220)',
                        borderWidth:Utils.pixel,
                        fontSize: 15 ,
                        marginRight:14,
                        //marginTop:4
                    }}>
                        {txt}
                    </Text>
                )
            }
        }
    }

这样大体就完成了。
码云 中有全部的代码。欢迎下载。
https://gitee.com/yizhi108/react-native-location/
如有其它问题,欢迎留言讨论。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 1.背景 本文使用的RN(使用RN表示React Native)的版本为0.44版本,从官方文档上看Section...
    这真不是玩笑阅读 17,867评论 17 54
  • 对于一个好的程序员,如果你需要大量使用一个框架,是无法忍受自己不知道这个框架的原理的,起初你可能只是调调api,慢...
    bigtom阅读 1,423评论 0 3
  • 两心相隔数千里, 梦中只差几厘米。 昨夜三更大风起, 一看朝南忙吹笛。 愿君明白我的意, 不要看信心不理。 一一彭...
    彭甫阅读 167评论 1 8
  • 北冥国 联姻大典 太子北冥尘轩看了看下面跪着的官家小姐,心想:“特么阿泠在就好了啊…全部送给他好了啊啊啊…”想着...
    莫羽汐阅读 126评论 0 0
  • 一、概念 vsftpd虚拟用户:不是系统用户,即虚拟用户在系统中是不存在的,不能用来登录系统。他们的总体权限其实是...
    指间_流年阅读 220评论 0 0