欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

android-仿手机通讯录(支持索引导航和搜索功能)

程序员文章站 2024-02-27 21:11:15
...

最近公司需要实现类似于手机通讯录的功能,并支持搜索功能,今天便简单写了一下。基本功能已经实现。我们先看一下效果。联系QQ878586063。以下晒出来的代码,是全部代码。代码不多,大家感受一下。
android-仿手机通讯录(支持索引导航和搜索功能)android-仿手机通讯录(支持索引导航和搜索功能)android-仿手机通讯录(支持索引导航和搜索功能)

首页我们看下索引导航View,特别简单一看就懂,这个类已经用模拟器试过除了手表所有的机型,都是可以的。

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < codes.length; i++) {
            if (codes[i].equals("#")) {
                canvas.drawBitmap(mBitmap, 8 * displayMetrics.density, lineHeight * (i + 1), paint);
            } else {
                canvas.drawText(codes[i], 10 * displayMetrics.density, 7 * displayMetrics.density + lineHeight * (i + 1), paint);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension((int) (viewHeight * displayMetrics.density), (int) (lineHeight * codes.length + 13 * displayMetrics.density));
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                setAlpha(0.5f);
                setBackgroundColor(Color.GRAY);
                float y = event.getY();
                int v = (int) ((y - 6.5 * displayMetrics.density) / lineHeight);
                if (v >= 0 && v <= codes.length - 1) {
                    if (moveEvent != null)
                        moveEvent.move(codes[v]);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                y = event.getY();
                v = (int) ((y - 6.5 * displayMetrics.density) / lineHeight);
                if (v >= 0 && v <= codes.length - 1) {
                    if (moveEvent != null)
                        moveEvent.move(codes[v]);
                }
                break;
            case MotionEvent.ACTION_UP:
                setBackgroundColor(Color.WHITE);
                setAlpha(1f);
                break;
        }
        return super.onTouchEvent(event);
    }

接下来我们看下怎么处理的:

//数据类
 *
 * Created by yang pengtao on 2017/9/19.
 */
public class SelectCountryCodeBean implements Serializable {

    private List<CodesBean> codes;

    public List<CodesBean> getCodes() {
        return codes;
    }

    public void setCodes(List<CodesBean> codes) {
        this.codes = codes;
    }

    public static class CodesBean {
        /**
         * cname : 福克兰群岛(马尔维纳斯)
         * ename : Falkland Islands (Islas Malvinas)
         * code : +500
         */

        private String cname;
        private String ename;
        private String code;
        private String first_letter;
        private int type = 1;

        public String getCname() {
            return cname;
        }

        public void setCname(String cname) {
            this.cname = cname;
        }

        public String getEname() {
            return ename;
        }

        public void setEname(String ename) {
            this.ename = ename;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getFirst_letter() {
            return first_letter;
        }

        public void setFirst_letter(String first_letter) {
            this.first_letter = first_letter;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }
    }
}

我们得到数据后先要处理一下,用pinyin4j.jar得到汉字拼音首字母,还要得到字母显示在列表中的下标,用于我们列表滚动。如果大家需要pinyin4j.jar。戳这里

/**
     * 重置数据成自己想要的数据
     *
     * @param data 要被重置的数据
     */
    private void resetData(List<SelectCountryCodeBean.CodesBean> data) {
        for (int i = 0; i < data.size(); i++) {
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(data.get(i).getCname().charAt(0));
            if (pinyinArray != null) {
                String s = pinyinArray[0].substring(0, 1).toUpperCase();
                data.get(i).setFirst_letter(s);
                if (!positions.containsKey(s)) {
                    positions.put(s, i);
                }
            }
        }
    }

有了数据我们就可以把数据显示到我们的列表上了,我用到了我写的上一篇封装的适配器,用起来非常方便,不用编写adapter和view holder,看下面代码,感受一下。希望大家赶快用起来吧。想学习的可以直接看暴力封装Adapter

 /**
     * 设置adapter
     */
    private void setAdapter() {
        listview.setAdapter(new BaseAdapter<SelectCountryCodeBean.CodesBean>(R.layout.layout_select_country_code, codes) {

            @Override
            public void onBindViewHolder(BaseViewHolder holder, List<SelectCountryCodeBean.CodesBean> data, int position) {
                if (position != 0 && data.get(position).getFirst_letter().equals(data.get(position - 1).getFirst_letter())) {
                    holder.getView(R.id.code).setVisibility(View.GONE);
                } else {
                    holder.getView(R.id.code).setVisibility(View.VISIBLE);
                }
                holder.setText(R.id.code, data.get(position).getFirst_letter());
                holder.setText(R.id.country, data.get(position).getCname() + "(" + data.get(position).getEname() + ")").setText(R.id.country_code, data.get(position).getCode());
            }


        });
    }

实现索引导航的代码也只不过仅仅几行,来感受虾:

 /**
     * 索引导航
     */
    private void indexNavigae() {
        ((ZoomImageView) findViewById(R.id.leftView)).setMoveEvent(new ZoomImageView.MoveEvent() {
            @Override
            public void move(String code) {
                if (positions.get(code) != null) {
                    linearLayoutManager.scrollToPositionWithOffset(positions.get(code), 0);
                }

            }
        });
    }

最后就只有我们的搜索功能,闲话不多说,直接感受:

/**
     * 搜索数据
     *
     * @param s 搜索字符
     */
    public void searchResetData(String s) {
        serachData.clear();
        //如果为null,直接使用全部数据
        if (s.equals("")) {
            serachData.addAll(codes);
        } else {
            //否则,匹配相应的数据
            for (int i = 0; i < codes.size(); i++) {
                if (codes.get(i).getCname().indexOf(s) >= 0 || codes.get(i).getEname().indexOf(s) >= 0) {//这里可拓展自己想要的,甚至可以拆分搜索汉字来匹配
                    serachData.add(codes.get(i));
                }
            }
        }
        //绑定索引
        positions.clear();
        resetData(serachData);
        //刷新数据
        ((BaseAdapter<SelectCountryCodeBean.CodesBean>) listview.getAdapter()).setmData(serachData);
    }

最后有一点非常重要:给IndexNavigateView加一个click事件,否则触摸事件回合recyclerView冲突。

到这就结束了,是不是特别简单,欢迎评论反馈。大家支持一下。

相关标签: 通讯录 android