您的位置:新葡亰496net > 服务器网络 > 新葡亰496net:仿美团网,js_脚本之家

新葡亰496net:仿美团网,js_脚本之家

发布时间:2019-11-24 05:31编辑:服务器网络浏览(60)

    在开发中有个需求是一个选择城市的列表,看了看做成三级联动好像不是特别方便 还是做成一整页可以按导航选取的就可以了

    本文实例讲述了PHP实现获取第一个中文首字母并进行排序的方法。分享给大家供大家参考,具体如下:

    相信绝大部分LBS的APP里面,大家都能看到一个带索引的城市列表页面,用来让用户选择所在城市。

    记得在我刚开始接触到美团网的时候就对美团网这个城市定位、选择城市功能很感兴趣,觉得它做得很棒。有如下几个点:
    一:实现ListView的A-Z字母排序功能
    二:根据输入框的输入值改变来过滤搜索结果,如果输入框里面的值为空,更新为原来的列表,否则为过滤数据列表
    三:汉字转成拼音的功能,很多时候实现联系人或者城市列表等实现A-Z的排序功能,我们可以直接从数据库中获取他的汉字拼音,而对于一般的数据,我们怎么实现A-Z的排序,这里我使用了PinYin4j.jar将汉字转换为拼音.
    按照惯例先来看一下最终效果图:

    新葡亰496net,在做单词本的时候,由于后台直接把所有的单词返回给我,所以需要自己将它们按首字母A-Z进行分类且放进新的数组里头。

    我用的是vant这个ui框架中的IndexBar组件 其实这个组件已经把需要的都弄好了 我们只要处理数据就好了

    最近在做储值结算,需求里结算首页需要按门店的首字母A-Z排序。我的数据结构原本是这样的:

    我们就一步一步的来实现这个页面,最终效果如下:

    这里写图片描述

    先看看处理前的数据 :

    首先需要引入IndexBar组件 这个就不再赘述了 官网写的很清楚

    Array( [0] => Array ( [sid] => 2885842 [recetcstoredpay] => 24000 [recetclprinciple] => 23465 [paytcstoredpay] => 5455 [paytclprinciple] => 34900 [sname] => 百宴餐饮---便宜坊烤鸭店 ) [1] => Array ( [sid] => 3644191 [recetcstoredpay] => 89200 [recetclprinciple] => 406930 [paytcstoredpay] => 4090 [paytclprinciple] => 97800 [sname] => 大长秋餐饮中心 ) [2] => Array ( [sid] => 5229673 [recetcstoredpay] => 26000 [recetclprinciple] => 45930 [paytcstoredpay] => 24795 [paytclprinciple] => 121800 [sname] => 大众点评网 ) [3] => Array ( [sid] => 3715927 [recetcstoredpay] => 13600 [recetclprinciple] => 56930 [paytcstoredpay] => 5710 [paytclprinciple] => 37800 [sname] => 江东北路店 ) [4] => Array ( [sid] => 3671092 [recetcstoredpay] => 1280 [recetclprinciple] => 46930 [paytcstoredpay] => 128090 [paytclprinciple] => 149800 [sname] => 金凤区新馆 ) [5] => Array ( [sid] => 1858783 [recetcstoredpay] => 2040 [recetclprinciple] => 4465 [paytcstoredpay] => 245 [paytclprinciple] => 4900 [sname] => 浙江西子宾馆 ) [6] => Array ( [sid] => 16832117 [recetcstoredpay] => 81600 [recetclprinciple] => 470930 [paytcstoredpay] => 506090 [paytclprinciple] => 8000 [sname] => 欢乐谷店 ))
    

    新葡亰496net 1Paste_Image.png

    接下来分析下整个功能模块的布局结构:
    (1)首先一个带删除按钮的EditText,我们在输入框中输入我们查找的城市可以自动过滤出最终的结果,当输入框中没有数据自动替换到原来的数据列表;
    (2)中间是当前定位的城市和热门的城市,其中热门城市使用到了GridView;
    (3)下面是一个ListView用来显示数据列表,右侧是一个字母索引表,当我们点击不同的字母,ListView会定位到该字母地方
    现在我们来看下项目结构图

    新葡亰496net 2处理前的数据.png

    点击索引栏时,会自动跳转到对应的IndexAnchor锚点位置

    根据需求,要根据sname的第一个汉字首字母排序,那么就先需要写一个取首字母的方法:

    最终我们会按照首字母汉语拼音对所有城市进行排序,可以通过右侧的首字母索引来快速定位到城市。

    这里写图片描述

    Share my code...

             ...
    
    /*** 取汉字的第一个字的首字母* @param type $str* @return string|null*/public function _getFirstCharter{if{return '';}$fchar=ord;if&&$fchar<=ord return strtoupper;$s1=iconv('UTF-8','gb2312',$str);$s2=iconv;$s=$s2==$str?$s1:$str;$asc=ord-65536;if($asc>=-20319&&$asc<=-20284) return 'A';if($asc>=-20283&&$asc<=-19776) return 'B';if($asc>=-19775&&$asc<=-19219) return 'C';if($asc>=-19218&&$asc<=-18711) return 'D';if($asc>=-18710&&$asc<=-18527) return 'E';if($asc>=-18526&&$asc<=-18240) return 'F';if($asc>=-18239&&$asc<=-17923) return 'G';if($asc>=-17922&&$asc<=-17418) return 'H';if($asc>=-17417&&$asc<=-16475) return 'J';if($asc>=-16474&&$asc<=-16213) return 'K';if($asc>=-16212&&$asc<=-15641) return 'L';if($asc>=-15640&&$asc<=-15166) return 'M';if($asc>=-15165&&$asc<=-14923) return 'N';if($asc>=-14922&&$asc<=-14915) return 'O';if($asc>=-14914&&$asc<=-14631) return 'P';if($asc>=-14630&&$asc<=-14150) return 'Q';if($asc>=-14149&&$asc<=-14091) return 'R';if($asc>=-14090&&$asc<=-13319) return 'S';if($asc>=-13318&&$asc<=-12839) return 'T';if($asc>=-12838&&$asc<=-12557) return 'W';if($asc>=-12556&&$asc<=-11848) return 'X';if($asc>=-11847&&$asc<=-11056) return 'Y';if($asc>=-11055&&$asc<=-10247) return 'Z';return null;}
    

    城市列表,下载地址:

    按照项目中类的顺序来一一介绍
    1.PinYin4j.jar用于将汉字转换为拼音,你还可以使用其他方式将汉子转换为拼音,我之前有介绍过,这里就不详讲啦,探索PinYin4j.jar将汉字转换为拼音的基本用法
    2.CitySortModel一个实体类,一个显示的城市和相对应的拼音首字母

     let WordList = [];//处理后的数组 for(let i=0;i<26;i  ){ const key = String.fromCharCode //A-Z赋给key当作键 let map = {} map[key] = { title: key, items: [] } this.data.List.map=>{ //遍历单词本 let firstIndex = v.WordName.substr;//首字母 if(firstIndex.toUpperCase() == String.fromCharCode{//统一转成大写进行逐个判断 map[key].items.push(v.WordName)//push进相对应的数组里头 } }) //如果当前的数组里头为空,则跳过。 if(map[key].items === undefined || map[key].items.length == 0){ continue; }else{ WordList.push//将分类好的每个对象 合并在一个数组里面 } } //给data里头声明的WordList赋值。(这里的情景是小程序) this.setData({ WordList:WordList })
    

    这是vant官方文档IndexBar的基本用法文档

    然后下一步,要对这个二维数据排序。我思考了很久,后来想到了方案,先在循环里调用这个取首字母的方法,然后以这个字母作为key,因为php里有根据key排序的方法,所以我的代码写成这样就搞定了:

    链接: 密码: cjpw

    package com.adan.selectcitydome.view;
    
    public class CitySortModel {
    
        private String name;//显示的数据
        private String sortLetters;//显示数据拼音的首字母
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSortLetters() {
            return sortLetters;
        }
    
        public void setSortLetters(String sortLetters) {
            this.sortLetters = sortLetters;
        }
    }
    

    这是处理后的数据截图。顺利将单词按A-Z分类~

    IndexAnchor默认是A-Z这里我们不用去自定义

    //门店名称$shopData = $this->_shopNamesArray;//根据门店名称第一个汉字的首字母正序排序$settles = $result['data'];$settlesRes = array();foreach  { $sname = $shopData[$sett['sid']]; $sett['sname'] = $sname; $snameFirstChar = $this->_getFirstCharter; //取出门店的第一个汉字的首字母 $settlesRes[$snameFirstChar] = $sett;//以这个首字母作为key}ksort; //对数据进行ksort排序,以key的值升序排序
    
    - (NSDictionary *)loadCityListData{ return [NSDictionary dictionaryWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"cityList.plist" withExtension:nil]];}
    

    3.EditTextWithDel类是自定义的一个带清除功能的输入框控件,也可以用Android原生的EditText,这个类上一篇博客有介绍,这里就不贴上代码了Android 带清除功能的输入框控件EditTextWithDel
    4.MyGridView类就是自定义GridView,主要是解决了在热门城市中嵌套Grideview的显示不完全的问题

    新葡亰496net 3处理后.png

    循环部分 我的思路是按每个城市名称的首个字母排序

    先把这些数据print出来看效果:

    • 字典中有一个属性allKeys,可以取出字典中所有的key。这是一个只读的属性。
    • 根据allKeys就能知道字典中有多少组,去对应的数据源设置返回数据。
    package com.adan.selectcitydome.view;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.widget.GridView;
    
    /**
     * 自定义GridView,解决嵌套Grideview的显示不完全的问题
     */
    public class MyGridView extends GridView {
    
        public MyGridView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public MyGridView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyGridView(Context context) {
            super(context);
        }
    
        /**
         * 其中onMeasure函数决定了组件显示的高度与宽度;
         * makeMeasureSpec函数中第一个函数决定布局空间的大小,第二个参数是布局模式
         * MeasureSpec.AT_MOST的意思就是子控件需要多大的控件就扩展到多大的空间
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
            int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                    MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
        }
    
    }
    

    小结

    新葡亰496net:仿美团网,js_脚本之家。这种处理方式虽然能实现效果但是在性能方面影响很大。想一想,for循环嵌套map遍历,如果原来的数组长度很大,那个处理速度一定很慢。参考下我同事的做法~简单明了。比♥

    封装个formatList(arr,keyword)方法。arr需要处理的数组名称,keyword数组里头的字段名。

    function formatList(arr,keyword) { let newArr1 = []; let tempArr = []; let reg = /b|s/g; let k = 0; let firstWord = arr[0][keyword].charAt.toUpperCase();//获取第一个分类字母 arr.map => { v[keyword] = v[keyword].replace(reg,m=>m.toUpperCase;//首字母大写 if(firstWord == v[keyword].charAt{ tempArr.push; newArr1[k] = { Title:firstWord, List:tempArr } }else{ //这里循环到这表示已经第二个字母了 firstWord = v[keyword].charAt;//设置第二字母 tempArr = [];//把之前的清除掉 tempArr.push;//添加第一个 newArr1[  k] = {//自增 Title: firstWord, List : tempArr } } }); return newArr1;}
    

    方法调用

     var newList = formatList(list,'WordName');
    

    好了~学习一波先。喜欢的小伙伴们可以点个赞哦。

    { "id": 101, "name": "北京市", "pid": 1, "code": 0},{ "id": 10101, "name": "天津市", "pid": 10001, "code": 0},{ "id": 20101, "name": "石家庄市", "pid": 20001, "code": 130100} 
    
    Array( [B] => Array ( [sid] => 2885842 [recetcstoredpay] => 24000 [recetclprinciple] => 23465 [paytcstoredpay] => 5455 [paytclprinciple] => 34900 [sname] => 百宴餐饮---便宜坊烤鸭店 ) [D] => Array ( [sid] => 5229673 [recetcstoredpay] => 26000 [recetclprinciple] => 45930 [paytcstoredpay] => 24795 [paytclprinciple] => 121800 [sname] => 大众点评网 ) [H] => Array ( [sid] => 16832117 [recetcstoredpay] => 81600 [recetclprinciple] => 470930 [paytcstoredpay] => 506090 [paytclprinciple] => 8000 [sname] => 欢乐谷店 ) [J] => Array ( [sid] => 3671092 [recetcstoredpay] => 1280 [recetclprinciple] => 46930 [paytcstoredpay] => 128090 [paytclprinciple] => 149800 [sname] => 金凤区新馆 ) [Z] => Array ( [sid] => 1858783 [recetcstoredpay] => 2040 [recetclprinciple] => 4465 [paytcstoredpay] => 245 [paytclprinciple] => 4900 [sname] => 浙江西子宾馆 ))
    

    5.PinyinComparator类用来对ListView中的数据根据A-Z进行排序,前面两个if判断主要是将不是以汉字开头的数据放在后面

    因为之前的数据很乱 所以我让后台老哥重新写了一个只包含市级城市的列表 这样就非常好处理了

    PS:这里再为大家推荐2款比较实用的相关在线排序工具供大家参考使用:

    @property (readonly, copy) NSArray<KeyType> *allKeys;
    
    package com.adan.selectcitydome.view;
    
    import java.util.Comparator;
    
    /**
     * 用来对ListView中的数据根据A-Z进行排序,前面两个if判断主要是将不是以汉字开头的数据放在后面
     */
    public class PinyinComparator implements Comparator<CitySortModel> {
    
        public int compare(CitySortModel o1, CitySortModel o2) {
            //这里主要是用来对ListView里面的数据根据ABCDEFG...来排序
            if (o1.getSortLetters().equals("@")
                    || o2.getSortLetters().equals("#")) {
                return -1;
            } else if (o1.getSortLetters().equals("#")
                    || o2.getSortLetters().equals("@")) {
                return 1;
            } else {
                return o1.getSortLetters().compareTo(o2.getSortLetters());
            }
        }
    }
    

    第一步先把城市的名称取出

    在线中英文根据首字母排序工具:

    • 对所有字典key的数组中的内容进行排序
    • 对于排序,系统提供了两种办法可以进行排序。我们就不用再写什么冒泡儿、选择之类的算法了,直接来就可以用。

    6.PinyinUtils类,就是第一点所讲的PinYin4j.jar用于将汉字转换为拼音啦,这里就不粘贴代码啦
    7.SideBar类就是ListView右侧的字母索引View,我们需要使用setTextView(TextView mTextDialog)来设置用来显示当前按下的字母的TextView,以及使用setOnTouchingLetterChangedListener方法来设置回调接口,在回调方法onTouchingLetterChanged(String s)中来处理不同的操作

    let cityNameList = []for{ cityNameList.push}
    

    在线文本倒序翻转排序工具:

    package com.adan.selectcitydome.view;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Typeface;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    
    import com.adan.selectcitydome.R;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * ListView右侧的字母索引View
     */
    public class SideBar extends View {
    
        public static String[] INDEX_STRING = {"A", "B", "C", "D", "E", "F", "G", "H", "I",
                "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
                "W", "X", "Y", "Z"};
    
        private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
        private List<String> letterList;
        private int choose = -1;
        private Paint paint = new Paint();
        private TextView mTextDialog;
    
        public SideBar(Context context) {
            this(context, null);
        }
    
        public SideBar(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SideBar(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        private void init() {
            setBackgroundColor(Color.parseColor("#F0F0F0"));
            letterList = Arrays.asList(INDEX_STRING);
        }
    
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int height = getHeight();// 获取对应高度
            int width = getWidth();// 获取对应宽度
            int singleHeight = height / letterList.size();// 获取每一个字母的高度
            for (int i = 0; i < letterList.size(); i  ) {
                paint.setColor(Color.parseColor("#606060"));
                paint.setTypeface(Typeface.DEFAULT_BOLD);
                paint.setAntiAlias(true);
                paint.setTextSize(20);
                // 选中的状态
                if (i == choose) {
                    paint.setColor(Color.parseColor("#4F41FD"));
                    paint.setFakeBoldText(true);
                }
                // x坐标等于中间-字符串宽度的一半.
                float xPos = width / 2 - paint.measureText(letterList.get(i)) / 2;
                float yPos = singleHeight * i   singleHeight / 2;
                canvas.drawText(letterList.get(i), xPos, yPos, paint);
                paint.reset();// 重置画笔
            }
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            final int action = event.getAction();
            final float y = event.getY();// 点击y坐标
            final int oldChoose = choose;
            final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
            final int c = (int) (y / getHeight() * letterList.size());// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
    
            switch (action) {
                case MotionEvent.ACTION_UP:
                    setBackgroundColor(Color.parseColor("#F0F0F0"));
                    choose = -1;
                    invalidate();
                    if (mTextDialog != null) {
                        mTextDialog.setVisibility(View.GONE);
                    }
                    break;
                default:
                    setBackgroundResource(R.drawable.sidebar_background);
                    if (oldChoose != c) {
                        if (c >= 0 && c < letterList.size()) {
                            if (listener != null) {
                                listener.onTouchingLetterChanged(letterList.get(c));
                            }
                            if (mTextDialog != null) {
                                mTextDialog.setText(letterList.get(c));
                                mTextDialog.setVisibility(View.VISIBLE);
                            }
                            choose = c;
                            invalidate();
                        }
                    }
                    break;
            }
            return true;
        }
    
        public void setIndexText(ArrayList<String> indexStrings) {
            this.letterList = indexStrings;
            invalidate();
        }
    
        /**
         * 为SideBar设置显示当前按下的字母的TextView
         *
         * @param mTextDialog
         */
        public void setTextView(TextView mTextDialog) {
            this.mTextDialog = mTextDialog;
        }
    
        /**
         * 向外公开的方法
         *
         * @param onTouchingLetterChangedListener
         */
        public void setOnTouchingLetterChangedListener(
                OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
            this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
        }
    
        /**
         * 接口
         */
        public interface OnTouchingLetterChangedListener {
            void onTouchingLetterChanged(String s);
        }
    
    }
    

    ok现在我们就把城市的名称存到了cityNameList中了

    更多关于PHP相关内容感兴趣的读者可查看本站专题:《php排序算法总结》、《PHP数组操作技巧大全》、《php字符串用法总结》、《php常用函数与技巧总结》、《PHP错误与异常处理方法总结》、《php面向对象程序设计入门教程》及《php常见数据库操作技巧汇总》

     _firstLetterOfCitys = [_firstLetterOfCitys sortedArrayUsingSelector:@selector];
    
     _firstLetterOfCitys = [_firstLetterOfCitys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {// 升序排序 return [obj1 compare:obj2]; // 将序排序 return [obj2 compare:obj1]; // 乱序 return arc4random_uniform % 3 - 1; }];
    

    8.CityAdapter就是热门城市中GridView的适配器

    下面一步就是关键的一步了 直接将数组的首字母取出来并按照A-Z排序这里用到了一个插件pinyin 用它来将中文的首字母取出来首先安装

    希望本文所述对大家PHP程序设计有所帮助。

    • 之所以是能够排序,是每次obj1和obj2比较都进行了一次排序。排序结果记录在了NSComparisonReuslt中。
    • NSComparisonReuslt是一个枚举。通过操作两数比较的结果,进行排序。如果两数比较的结果一会儿是-1,一会儿是0,一会儿是1,那排序出来的结果也就是乱的。
    package com.adan.selectcitydome;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.LinearLayout;
    
    import java.util.List;
    
    /**
     * @author: xiaolijuan
     * @description:
     * @projectName: SelectCityDome
     * @date: 2016-03-01
     * @time: 17:25
     */
    public class CityAdapter extends ArrayAdapter<String> {
        /**
         * 需要渲染的item布局文件
         */
        private int resource;
    
        public CityAdapter(Context context, int textViewResourceId, List<String> objects) {
            super(context, textViewResourceId, objects);
            resource = textViewResourceId;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LinearLayout layout = null;
            if (convertView == null) {
                layout = (LinearLayout) LayoutInflater.from(getContext()).inflate(resource, null);
            } else {
                layout = (LinearLayout) convertView;
            }
            Button name = (Button) layout.findViewById(R.id.tv_city);
            name.setText(getItem(position));
            return layout;
        }
    }
    
    npm install js-pinyin
    

    官方对此说明:

    9.SortAdapter 数据的适配器类,这里我们需要用到的就是SectionIndexer接口,它能够有效地帮助我们对分组进行控制。使用SectionIndexer接口需要实现三个方法:getSectionForPosition(int position),getPositionForSection(int section),getSections(),我们只需要自行实现前面两个方法:
    (一)getSectionForPosition(int position)是根据ListView的position来找出当前位置所在的分组
    getPositionForSection(int section)就是根据首字母的Char值来获取在该ListView中第一次出现该首字母的位置,也就是当前分组所在的位置

    然后我是在mian.js中引入的

    typedef NS_ENUM(NSInteger, NSComparisonResult) {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending};
    
    package com.adan.selectcitydome;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.SectionIndexer;
    import android.widget.TextView;
    
    import com.adan.selectcitydome.view.CitySortModel;
    
    import java.util.List;
    
    public class SortAdapter extends BaseAdapter implements SectionIndexer {
        private List<CitySortModel> list = null;
        private Context mContext;
    
        public SortAdapter(Context mContext, List<CitySortModel> list) {
            this.mContext = mContext;
            this.list = list;
        }
    
        /**
         * 当ListView数据发生变化时,调用此方法来更新ListView
         *
         * @param list
         */
        public void updateListView(List<CitySortModel> list) {
            this.list = list;
            notifyDataSetChanged();
        }
    
        public int getCount() {
            return this.list.size();
        }
    
        public Object getItem(int position) {
            return list.get(position);
        }
    
        public long getItemId(int position) {
            return position;
        }
    
        public View getView(final int position, View view, ViewGroup arg2) {
            ViewHolder viewHolder = null;
            final CitySortModel mContent = list.get(position);
            if (view == null) {
                viewHolder = new ViewHolder();
                view = LayoutInflater.from(mContext).inflate(R.layout.item_select_city, null);
                viewHolder.tvTitle = (TextView) view.findViewById(R.id.tv_city_name);
                view.setTag(viewHolder);
                viewHolder.tvLetter = (TextView) view.findViewById(R.id.tv_catagory);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }
    
            int section = getSectionForPosition(position);
    
            if (position == getPositionForSection(section)) {
                viewHolder.tvLetter.setVisibility(View.VISIBLE);
                viewHolder.tvLetter.setText(mContent.getSortLetters());
            } else {
                viewHolder.tvLetter.setVisibility(View.GONE);
            }
    
            viewHolder.tvTitle.setText(this.list.get(position).getName());
    
            return view;
    
        }
    
    
        final static class ViewHolder {
            TextView tvLetter;
            TextView tvTitle;
        }
    
        public int getSectionForPosition(int position) {
            return list.get(position).getSortLetters().charAt(0);
        }
    
        public int getPositionForSection(int section) {
            for (int i = 0; i < getCount(); i  ) {
                String sortStr = list.get(i).getSortLetters();
                char firstChar = sortStr.toUpperCase().charAt(0);
                if (firstChar == section) {
                    return i;
                }
            }
            return -1;
        }
    
        @Override
        public Object[] getSections() {
            return null;
        }
    }
    
    import pinyin from 'js-pinyin'
    
    • 边栏的索引显示的文字和实际跳转没有直接关系。
    • 边栏索引无论写什么,都是按照实际的key值进行跳转的。

    10.MainActivity 对EditTextWithDel设置addTextChangedListener监听,当输入框内容发生变化根据里面的值过滤ListView,里面的值为空显示原来的列表和给ListView添加表头等

    然后在你的业务页面配置

    package com.adan.selectcitydome;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.text.Editable;
    import android.text.TextUtils;
    import android.text.TextWatcher;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.GridView;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.adan.selectcitydome.view.CitySortModel;
    import com.adan.selectcitydome.view.EditTextWithDel;
    import com.adan.selectcitydome.view.PinyinComparator;
    import com.adan.selectcitydome.view.PinyinUtils;
    import com.adan.selectcitydome.view.SideBar;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class MainActivity extends Activity {
        private ListView sortListView;
        private SideBar sideBar;
        private TextView dialog, mTvTitle;
        private SortAdapter adapter;
        private EditTextWithDel mEtCityName;
        private List<CitySortModel> SourceDateList;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initViews();
        }
    
        private void initViews() {
            mEtCityName = (EditTextWithDel) findViewById(R.id.et_search);
            sideBar = (SideBar) findViewById(R.id.sidrbar);
            dialog = (TextView) findViewById(R.id.dialog);
            mTvTitle = (TextView) findViewById(R.id.tv_title);
            sortListView = (ListView) findViewById(R.id.country_lvcountry);
            initDatas();
            initEvents();
            setAdapter();
        }
    
        private void setAdapter() {
            SourceDateList = filledData(getResources().getStringArray(R.array.provinces));
            Collections.sort(SourceDateList, new PinyinComparator());
            adapter = new SortAdapter(this, SourceDateList);
            sortListView.addHeaderView(initHeadView());
            sortListView.setAdapter(adapter);
        }
    
        private void initEvents() {
            //设置右侧触摸监听
            sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {
                @Override
                public void onTouchingLetterChanged(String s) {
                    //该字母首次出现的位置
                    int position = adapter.getPositionForSection(s.charAt(0));
                    if (position != -1) {
                        sortListView.setSelection(position   1);
                    }
                }
            });
    
            //ListView的点击事件
            sortListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    
                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                                        int position, long id) {
                    mTvTitle.setText(((CitySortModel) adapter.getItem(position - 1)).getName());
                    Toast.makeText(getApplication(), ((CitySortModel) adapter.getItem(position)).getName(), Toast.LENGTH_SHORT).show();
                }
            });
    
            //根据输入框输入值的改变来过滤搜索
            mEtCityName.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    
                }
    
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    //当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表
                    filterData(s.toString());
                }
    
                @Override
                public void afterTextChanged(Editable s) {
    
                }
            });
        }
    
        private void initDatas() {
            sideBar.setTextView(dialog);
        }
    
        private View initHeadView() {
            View headView = getLayoutInflater().inflate(R.layout.headview, null);
            GridView mGvCity = (GridView) headView.findViewById(R.id.gv_hot_city);
            String[] datas = getResources().getStringArray(R.array.city);
            ArrayList<String> cityList = new ArrayList<>();
            for (int i = 0; i < datas.length; i  ) {
                cityList.add(datas[i]);
            }
            CityAdapter adapter = new CityAdapter(getApplicationContext(), R.layout.gridview_item, cityList);
            mGvCity.setAdapter(adapter);
            return headView;
        }
    
        /**
         * 根据输入框中的值来过滤数据并更新ListView
         *
         * @param filterStr
         */
        private void filterData(String filterStr) {
            List<CitySortModel> mSortList = new ArrayList<>();
            if (TextUtils.isEmpty(filterStr)) {
                mSortList = SourceDateList;
            } else {
                mSortList.clear();
                for (CitySortModel sortModel : SourceDateList) {
                    String name = sortModel.getName();
                    if (name.toUpperCase().indexOf(filterStr.toString().toUpperCase()) != -1 || PinyinUtils.getPingYin(name).toUpperCase().startsWith(filterStr.toString().toUpperCase())) {
                        mSortList.add(sortModel);
                    }
                }
            }
            // 根据a-z进行排序
            Collections.sort(mSortList, new PinyinComparator());
            adapter.updateListView(mSortList);
        }
    
        private List<CitySortModel> filledData(String[] date) {
            List<CitySortModel> mSortList = new ArrayList<>();
            ArrayList<String> indexString = new ArrayList<>();
    
            for (int i = 0; i < date.length; i  ) {
                CitySortModel sortModel = new CitySortModel();
                sortModel.setName(date[i]);
                String pinyin = PinyinUtils.getPingYin(date[i]);
                String sortString = pinyin.substring(0, 1).toUpperCase();
                if (sortString.matches("[A-Z]")) {
                    sortModel.setSortLetters(sortString.toUpperCase());
                    if (!indexString.contains(sortString)) {
                        indexString.add(sortString);
                    }
                }
                mSortList.add(sortModel);
            }
            Collections.sort(indexString);
            sideBar.setIndexText(indexString);
            return mSortList;
        }
    }
    
    let pinyin = requirepinyin.setOptions({checkPolyphone:false,charCase:0})
    
    - (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{ return _firstLetterOfCitys;}
    

    布局文件就不贴出来了,有兴趣的可以下载代码,有什么疑问的,请在下面留言,感谢各位_
    本项目改造自http://blog.csdn.net/xiaanming/article/details/12684155
    源代码请戳这里:Android 仿美团网,探索ListView的A-Z字母排序功能实现选择省份或者城市

    直接一个循环达到我们的效果

    • 所有的类方法在执行初始化的时候都需要先去看看类里面初始化的方法首选项。
    let firstName = {};this.FirstPin.forEach=>{ firstName[item] = []; cityNameList.forEach=>{ let first = pinyin.getFullChars; if{ firstName[item].push
    

    以UITableView为例

    这里的FirstPin是在data中定义的一个数组,用来存储A-Z

    NS_CLASS_AVAILABLE_IOS @interface UITableView : UIScrollView <NSCoding>- (instancetype)initWithFrame:frame style:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
    
     FirstPin: ["A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "W", "X", "Y", "Z"],
    

    官方说明的意思是说,当执行init的时候,系统要求执行了两个初始化方法。

    然后我的firstName的格式是这样的

    问题来了:如果在初始化的时候,写成了[[UITableView alloc] init],在编译的时候实际上还是执行了两个初始化方法。第一个初始化方法中要求传入frame,此时因为没有传入参数,frame就会被默认为{0.0.0.0}。

    firName:{ A:["阿拉善盟","鞍山市"]}
    

    为了解决这个问题,当view有了frame之后,就需要重新给tableView设置frame。是用以下方法进行设置:

    最后在InderBar组件中写一个循环就可以了

    - layoutSubviews{ [super layoutSubviews]; _tableView.frame = self.bounds;}
    
      {{index}}   
    

    因为城市列表今后我们很有可能会在其他项目里面使用,但我们又不确定以后再使用的时候是用StoryBoard调用还是代码调用。所以我们还要进一步处理一下。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    //当从XIB或者UIStoryboard中创建UITableView的时候加载此方法- awakeFromNib{ [super awakeFromNib]; [self createCityListTableView];}//使用代码创建的时候加载此方法- (instancetype)initWithFrame:frame{ self = [super initWithFrame:frame]; if  { [self createCityListTableView]; } return self;}
    

    这样就算是封装好了,以后不管是SB还是代码方式,都可以直接的把刚才写好的城市列表进行引用了。

    本文由新葡亰496net发布于服务器网络,转载请注明出处:新葡亰496net:仿美团网,js_脚本之家

    关键词: