由于项目需要做一个仿通讯录搜索联系人的功能,并且需要选中联系人,即推荐好友的功能。所以就想写一遍blog来介绍它是怎么实现,以及是怎么用的。好的,接下来,让我为大家讲解一下它是怎么生出来的。
首先,给大家上一个功能示例图。

android 怎么全局搜索 安卓手机全部搜索列表_ide

android 怎么全局搜索 安卓手机全部搜索列表_通讯录_02


android 怎么全局搜索 安卓手机全部搜索列表_android 怎么全局搜索_03

android 怎么全局搜索 安卓手机全部搜索列表_搜索_04

以上四张图片是通过本人截图所得的,虽然不是很好看,但大概意思应该都能明白。大致有3个分类功能:一是输入框搜索,二是侧边栏搜索,三是联系人的单选,全选以及反选功能。那下面,我们进行一一讲解。

1. 获取通讯录联系人的信息:姓名、电话号码。

    ## 注意哦,需要添加读取权限 ##
<!-- 读取联系人权限 -->
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    ```

## 具体获取联系人的代码如下 ##
    ```
/**得到手机通讯录联系人信息**/
    private void getPhoneContacts() {
        ContentResolver resolver = getContentResolver();
        // 获取手机联系人
        Cursor phoneCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,PHONES_PROJECTION, null, null, null);
        persons = new ArrayList<Person>();
        if (phoneCursor != null) {

            while (phoneCursor.moveToNext()) {
                //得到手机号码
                String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX).toString().trim();
                Log.e("xxx",phoneNumber);
                //当手机号码为空的或者为空字段 跳过当前循环
                if (TextUtils.isEmpty(phoneNumber))
                    continue;
                //得到联系人名称
                String contactName = phoneCursor.getString(PHONES_DISPLAY_NAME_INDEX);
                Person p21 = new Person(contactName,phoneNumber);
                persons.add(p21);
            }
            phoneCursor.close();
        }
        mHandler.sendEmptyMessage(0);
    }
2. 根据输入框输入关键字搜索联系人。
 ##中文转英文##
/**
     * 中文转英文
     *
     * @param src
     * @return
     */
    public static String getPingYin(String src) {
        char[] t1 = null;
        t1 = src.toCharArray();
        String[] t2 = new String[t1.length];
        HanyuPinyinOutputFormat t3 = new HanyuPinyinOutputFormat();
        t3.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        t3.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        t3.setVCharType(HanyuPinyinVCharType.WITH_V);
        String t4 = "";
        int t0 = t1.length;
        try {
            for (int i = 0; i < t0; i++) {
                // 判断是否为汉字字符
                if (java.lang.Character.toString(t1[i]).matches(
                        "[\\u4E00-\\u9FA5]+")) {
                    t2 = PinyinHelper.toHanyuPinyinStringArray(t1[i], t3);
                    t4 += t2[0];
                } else {
                    t4 += java.lang.Character.toString(t1[i]);
                }
            }
            return t4;
        } catch (BadHanyuPinyinOutputFormatCombination e1) {
            e1.printStackTrace();
        }
        return t4;
    }
## 中文首字母缩写 ##
/**
     * 得到中文首字母缩写
     *
     * @param str
     * @return
     */
    public static String getPinYinHeadChar(String str) {

        String convert = "";
        for (int j = 0; j < str.length(); j++) {
            char word = str.charAt(j);
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
            if (pinyinArray != null) {
                convert += pinyinArray[0].charAt(0);
            } else {
                convert += word;
            }
        }
        return convert.toUpperCase();
    }
## 根据字母搜索 ##
其主要原理是通过比对输入的关键字与程序所存的通讯录数组中的拼音(中文转拼音)。现在这里做的只要是包含该关键字的拼音,都搜索出来,并没有根据通讯录中姓名的首字母进行搜索,当然,如果要实现的话,也是可以的。
/**
     * 根据字母拼音搜索
     * @param letter
     */
    private void searchbyLetter(final String letter) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                getData(letter);
            }
        }).start();
    }
    private void getData(String ll) {
        letters.clear();
        for(Person p:persons){
            if(p.getPinYinName().contains(StringHelper.CapitalToSmallLetter(ll))){
                letters.add(p);
            }
        }
        Message msg = new Message();
        msg.what = 3;
        mHandler.sendMessage(msg);
    }
## 根据中文搜索 ##
其主要原理大致与上面一致。
/**
     * 根据中文搜索
     * @param search
     */
    private void searchbyChinese(final String search) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                getChineseData(search);
            }
        }).start();
    }

    private void getChineseData(String search) {
        chineses.clear();
        for(Person p:persons){
            Log.e("xxx",p.getName()+">>>"+search);
            if(p.getName().contains(search)){
                chineses.add(p);
            }
        }
        Message msg = new Message();
        msg.what = 4;
        mHandler.sendMessage(msg);
    }
##区分输入的关键字是中文还是英文 ##
/**
     *  判断中文或者是英文
     * @param value
     * @return
     */
    public static boolean isLetter(String value){
//        Pattern p = Pattern.compile("[0-9]*");
//        Matcher m = p.matcher(value);
//        if(m.matches() ){
//            Toast.makeText(Main.this,"输入的是数字", Toast.LENGTH_SHORT).show();
//        }
//        p=Pattern.compile("[a-zA-Z]");
//        m=p.matcher(value);
//        if(m.matches()){
//            Toast.makeText(Main.this,"输入的是字母", Toast.LENGTH_SHORT).show();
//        }
        String flag = "";
        int len = value.length();
        Pattern p=Pattern.compile("[\u4e00-\u9fa5]");
        for(int i = 0;i < len ;i++){
            String s = value.substring(i,i+1);
            Log.e("xxx",s);
            Matcher m=p.matcher(s);
            if(m.matches()){
                flag += "tu"+",";
            }else{
                flag += "fa"+",";
            }
        }
        Log.e("xx",flag);
        if(flag != null && flag.contains("fa")){
            return false;
        }
        return true;
    }
3. 侧边栏滚动搜索。

    ## 绘制索引列表 ##
private String[] indexStr = { "#", "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" };
 @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        // 在oncreate里面执行下面的代码没反应,因为oncreate里面得到的getHeight=0
        if (!flag) {// 这里为什么要设置个flag进行标记,我这里不先告诉你们,请读者研究,因为这对你们以后的开发有好处
            height = layoutIndex.getMeasuredHeight() / indexStr.length;
            getIndexView();
            flag = true;
        }
    }
 /**
     * 绘制索引列表
     */
    public void getIndexView() {
        LinearLayout.LayoutParams params = new LayoutParams(
                LayoutParams.WRAP_CONTENT, height);
        for (int i = 0; i < indexStr.length; i++) {
            final TextView tv = new TextView(this);
            tv.setLayoutParams(params);
            tv.setText(indexStr[i]);
            tv.setPadding(10, 0, 10, 0);
            layoutIndex.addView(tv);
            layoutIndex.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event)

                {
                    float y = event.getY();
                    int index = (int) (y / height);
                    if (index > -1 && index < indexStr.length) {// 防止越界
                        String key = indexStr[index];
                        if (selector.containsKey(key)) {
                            int pos = selector.get(key);
                            if (listView.getHeaderViewsCount() > 0) {// 防止ListView有标题栏,本例中没有。
                                listView.setSelectionFromTop(
                                        pos + listView.getHeaderViewsCount(), 0);
                            } else {
                                listView.setSelectionFromTop(pos, 0);// 滑动到第一项
                            }
                            tv_show.setVisibility(View.VISIBLE);
                            tv_show.setText(indexStr[index]);
                        }
                    }
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            layoutIndex.setBackgroundColor(Color
                                    .parseColor("#f2f2f2"));
                            break;

                        case MotionEvent.ACTION_MOVE:

                            break;
                        case MotionEvent.ACTION_UP:
                            layoutIndex.setBackgroundColor(Color
                                    .parseColor("#00ffffff"));
                            tv_show.setVisibility(View.GONE);
                            break;
                    }
                    return true;
                }
            });
        }
    }
4. 联系人的单选,全选以及反选功能。

    ##适配器中配置接口##
interface onCheckChangeListen{
        void showBottom();
    }
    public void setOnCheckChange(onCheckChangeListen listen){
        this.mListen = listen;
    }
## 在主程序中进行调用 ##
//监听列表中checkbox的状态变化
            adapter.setOnCheckChange(new ListViewAdapter.onCheckChangeListen() {
                @Override
                public void showBottom() {
                    String flag = "";
                    count = 0;
                    for(Person p:newPersons){
                        flag += p.isChecked()+",";
                    }
                    Log.e("xxx",flag);
                    String[] value = flag.split(",");
                    for(int i=0;i<value.length;i++){
                        if(value[i].equals("true")){
                            count += 1 ;
                        }
                    }
                    if(count == 0){
                        mBottomLayout.setVisibility(View.GONE);
                    }else if(count > 0){
                        mBottomLayout.setVisibility(View.VISIBLE);
                        mPersonCount.setText("选中"+count+"个联系人");
                    }
                }
            });
## 全选与反选 ##
//全选or反选
        mCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){
                    for(Person p:newPersons){
                        p.setChecked(isChecked);
                    }
                    mCheck.setChecked(true);
                    adapter.notifyDataSetChanged();
                }else{
                    for(Person p:newPersons){
                        p.setChecked(false);
                    }
                    mCheck.setChecked(false);
                    adapter.notifyDataSetChanged();
                    mBottomLayout.setVisibility(View.GONE);
                }
            }
        });

以上就是构成该项目的主要代码。其完整的demo在下面。