美文网首页
android ListView根据字母排序和定位

android ListView根据字母排序和定位

作者: 静染星辰 | 来源:发表于2019-05-25 14:48 被阅读0次
    示例图

    1,右边的检索SideBar

    源码:

    public class SideBarextends View {

    private char[]l;

        private SectionIndexersectionIndexter =null;

        private ListViewlist;

        private TextViewmDialogText;

        Bitmapmbitmap;

        private int type =1;

        private int color =0xff858c94;

        public SideBar(Context context) {

    super(context);

            init();

        }

    public SideBar(Context context, AttributeSet attrs) {

    super(context, attrs);

            init();

        }

    private void init() {

    l =new char[] {'!','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','#'};

            mbitmap = BitmapFactory.decodeResource(getResources(),

                    R.drawable.scroll_bar_search_icon);

        }

    public SideBar(Context context, AttributeSet attrs, int defStyle) {

    super(context, attrs, defStyle);

            init();

        }

    public void setListView(ListView _list) {

    list = _list;

            ChooseCityAdapter ad = (ChooseCityAdapter) _list.getAdapter(); //listview适配器

            sectionIndexter = ad;

        }

    public void setTextView(TextView mDialogText) {

    this.mDialogText = mDialogText;

        }

    @Override

        public boolean onTouchEvent(MotionEvent event) {

    super.onTouchEvent(event);

            int i = (int) event.getY();

            int idx = i / (getMeasuredHeight() /l.length);

            if (idx >=l.length) {

    idx =l.length -1;

            }else if (idx <0) {

    idx =0;

            }

    if (event.getAction() == MotionEvent.ACTION_DOWN

                    || event.getAction() == MotionEvent.ACTION_MOVE) {

    setBackgroundResource(R.drawable.scrollbar_bg);

                mDialogText.setVisibility(View.VISIBLE);

                if (idx ==0) {

    mDialogText.setText("Search");

                    mDialogText.setTextSize(16);

                }else {

    mDialogText.setText(String.valueOf(l[idx]));

                    mDialogText.setTextSize(34);

                }

    if (sectionIndexter ==null) {

    sectionIndexter = (SectionIndexer)list.getAdapter();

                }

    int position =sectionIndexter.getPositionForSection(l[idx]);

                if (position == -1) {

    return true;

                }

    list.setSelection(position);

            }else {

    mDialogText.setVisibility(View.INVISIBLE);

            }

    if (event.getAction() == MotionEvent.ACTION_UP) {

    setBackgroundDrawable(new ColorDrawable(0x00000000));

            }

    return true;

        }

    @Override

        protected void onDraw(Canvas canvas) {

    Paint paint =new Paint();

            paint.setColor(color);

            paint.setTextSize(24);

            paint.setStyle(Paint.Style.FILL);

            paint.setTextAlign(Paint.Align.CENTER);

            float widthCenter = getMeasuredWidth() /2;

            if (l.length >0) {

    float height = getMeasuredHeight() /l.length;

                for (int i =0; i

    if (i ==0 &&type !=2) {

    canvas.drawBitmap(mbitmap, widthCenter -7, (i +1)

    * height - height /2, paint);

                    }else

                        canvas.drawText(String.valueOf(l[i]), widthCenter,

                                (i +1) * height, paint);

                }

    }

    this.invalidate();

            super.onDraw(canvas);

        }

    }

    2,适配器的更改

    适配器实现SectionIndexer接口,实现它的方法

    @Override

    public Object[]getSections() {

    return new Object[0];

    }

    public int getSectionForPosition(int position) {

    String letter = FirstLetterUtil.getFirstLetter(lists.get(position).getName()).toUpperCase();

      return letter.charAt(0);

    }

    public int getPositionForSection(int section) {

    for (int i =0; i < getCount(); i++) {

    String letter = FirstLetterUtil.getFirstLetter(lists.get(i).getName()).toUpperCase();

          char firstChar = letter.toUpperCase().charAt(0);

          if (firstChar == section) {

    return i;

          }

    }

    return -1;

    }

    3,关联listview与SideBar

    sideBar.setListView(lv_listview);

    sideBar.setTextView(tv_textview);

    4.其他

    1,获取汉字名称首字母

    public class FirstLetterUtil {

        private static int BEGIN =45217;

        private static int END =63486;

        // 按照声母表示,这个表是在GB2312中的出现的第一个汉字,也就是说“啊”是代表首字母a的第一个汉字。

        // i, u, v都不做声母, 自定规则跟随前面的字母

        private static char[]chartable = {'啊', '芭', '擦', '搭', '蛾', '发', '噶', '哈',

                '哈', '击', '喀', '垃', '妈', '拿', '哦', '啪', '期', '然', '撒', '塌', '塌',

                '塌', '挖', '昔', '压', '匝', };

        // 二十六个字母区间对应二十七个端点

        // GB2312码汉字区间十进制表示

        private static int[]table =new int[27];

        // 对应首字母区间表

        private static char[]initialtable = {'a', 'b', 'c', 'd', 'e', 'f', 'g',

                'h', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',

                't', 't', 'w', 'x', 'y', 'z', };

        // 初始化

        static {

            for (int i =0; i <26; i++) {

                table[i] =gbValue(chartable[i]);// 得到GB2312码的首字母区间端点表,十进制。

            }

            table[26] =END;// 区间表结尾

        }

    /**

        * 根据一个包含汉字的字符串返回一个汉字拼音首字母的字符串 最重要的一个方法,思路如下:一个个字符读入、判断、输出

        */

        public static StringgetFirstLetter(String sourceStr) {

            String result ="";

            String str = sourceStr.toLowerCase();

            int StrLength = str.length();

            int i;

            try {

                for (i =0; i < StrLength; i++) {

                    result +=Char2Initial(str.charAt(i));

                }

            }catch (Exception e) {

                result ="";

            }

        return result;

        }

    /**

        * 输入字符,得到他的声母,英文字母返回对应的大写字母,其他非简体汉字返回 '0'

    */

        private static char Char2Initial(char ch) {

    // 对英文字母的处理:小写字母转换为大写,大写的直接返回

            if (ch >='a' && ch <='z') {

                return ch;

            }

            if (ch >='A' && ch <='Z') {

                return ch;

            }

    // 对非英文字母的处理:转化为首字母,然后判断是否在码表范围内,

            // 若不是,则直接返回。

            // 若是,则在码表内的进行判断。

            int gb =gbValue(ch);// 汉字转换首字母

            if ((gb END))// 在码表区间之前,直接返回

            {

                return ch;

            }

            int i;

            for (i =0; i <26; i++) {// 判断匹配码表区间,匹配到就break,判断区间形如“[,)”

                if ((gb >=table[i]) && (gb

                    break;

                }

            }

            if (gb ==END) {// 补上GB2312区间最右端

                i =25;

            }

            return initialtable[i]; // 在码表区间中,返回首字母

        }

    /**

        * 取出汉字的编码 cn 汉字

        */

        private static int gbValue(char ch) {// 将一个汉字(GB2312)转换为十进制表示。

            String str =new String();

            str += ch;

            try {

                byte[] bytes = str.getBytes("GB2312");

                if (bytes.length <2) {

                    return 0;

                }

                return (bytes[0] <<8 &0xff00) + (bytes[1] &0xff);

            }catch (Exception e) {

                return 0;

            }

    }

    }

    2,listview数据排序

    Collections.sort(cityLists, new Comparator() {

    @Override

        public int compare(CityBean lhs, CityBean rhs) {

            String letter1 = FirstLetterUtil.getFirstLetter(lhs.getName()).toUpperCase();

            String letter2 = FirstLetterUtil.getFirstLetter(rhs.getName()).toUpperCase();

            //这里主要是用来对ListView里面的数据根据ABCDEFG...来排序

            if (letter1.equals("@") || letter2.equals("#")) {

                return -1;

            }else if (letter1.equals("#")    || letter2.equals("@")) {

                return 1;

            }else {

                   return letter1.compareTo(letter2);

            }

    }

    });

    3,适配器字母控件的显示隐藏

    String currentStr = FirstLetterUtil.getFirstLetter(cityBean.getName()).toUpperCase().substring(0,1);

    String index =null;

    if (position ==0) {

    index = currentStr;

    }else {

    String lastStr = FirstLetterUtil.getFirstLetter(lists.get(position -1).getName()).toUpperCase().substring(0,1);

      if (!TextUtils.equals(lastStr,currentStr)) {

    index = currentStr;

      }

    }

    viewHolder.tv_letter.setText(currentStr);

    //首字母相同的姓氏只显示第一个名字上面的首字母,其他的隐藏掉

    viewHolder.tv_letter.setVisibility(index ==null ? View.GONE : View.VISIBLE);

    **********************END*********************

    我是静染星辰,私人微信:azxy986753

    欢迎添加微信,互相学习,互相进步!

    相关文章

      网友评论

          本文标题:android ListView根据字母排序和定位

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