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

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

首页我们看下索引导航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 codes;

    public List getCodes() {
        return codes;
    }

    public void setCodes(List 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 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.CodesBean>(R.layout.layout_select_country_code, codes) {

            @Override
            public void onBindViewHolder(BaseViewHolder holder, List.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) listview.getAdapter()).setmData(serachData);
    }

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

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

你可能感兴趣的:(android)