自定义的通讯录实现方式一

  • 准备工作

/**
 * A~Z检索的list
 */
public class MyListView extends View {
    // 触摸事件
    OnTouchingLetterChangedListener onTouchingLetterChangedListener;
    String[] b = {"#", "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"};
    int choose = -1;
    Paint paint = new Paint();
    boolean showBkg = false;


    //显示弹出的内容
    private TextView mTextDialog;

    public void setTextView(TextView mTextDialog) {
        this.mTextDialog = mTextDialog;
    }


    public MyListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyListView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (showBkg) {//点击索引时的背景色
            canvas.drawColor(Color.parseColor("#f7f7fe"));
        }

        int height = getHeight();
        int width = getWidth();
        int singleHeight = height / b.length;// 获取每一个字母的高度
        for (int i = 0; i < b.length; i++) {
            paint.setColor(Color.BLACK);//A-Z字体的颜色
            paint.setTextSize(30);//字体的大小
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);
            // 选中的状态字体的变化
            if (i == choose) {
                paint.setColor(Color.parseColor("#3399ff"));
                paint.setFakeBoldText(true);
            }
            // x坐标等于中间-字符串宽度的一半.
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            float yPos = singleHeight * i + singleHeight;
            canvas.drawText(b[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;
        // 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
        final int c = (int) (y / getHeight() * b.length);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                showBkg = true;//按下时弹出
                if (oldChoose != c && listener != null) {
                    if (c >= 0 && c < b.length) {
                        listener.onTouchingLetterChanged(b[c]);
                        choose = c;
                        invalidate();
                    }
                }

                break;
            case MotionEvent.ACTION_MOVE:
                showBkg = true;//滚动时弹出
                if (oldChoose != c && listener != null) {
                    if (c >= 0 && c < b.length) {
                        listener.onTouchingLetterChanged(b[c]);
                        choose = c;
                        invalidate();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                showBkg = false;
                choose = -1;
                invalidate();
                break;
        }
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }

    /**
     * 向外公开的方法
     */
    public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    }

    public interface OnTouchingLetterChangedListener {
        public void onTouchingLetterChanged(String s);
    }

}

/**
 *  汉字转换为拼音类
 */
@SuppressWarnings("unchecked")
public class CnToSpell {
    private static LinkedHashMap spellMap = null;

    static {
        if (spellMap == null) {
            spellMap = new LinkedHashMap(400);
        }
        initialize();
        //      System.out.println("Chinese transfer Spell Done.");
    }

    private CnToSpell() {
    }

    private static void spellPut(String spell, int ascii) {
        spellMap.put(spell, new Integer(ascii));
    }

    private static void initialize() {
        spellPut("a", -20319);
        spellPut("ai", -20317);
        spellPut("an", -20304);
        spellPut("ang", -20295);
        spellPut("ao", -20292);
        spellPut("ba", -20283);
        spellPut("bai", -20265);
        spellPut("ban", -20257);
        spellPut("bang", -20242);
        spellPut("bao", -20230);
        spellPut("bei", -20051);
        spellPut("ben", -20036);
        spellPut("beng", -20032);
        spellPut("bi", -20026);
        spellPut("bian", -20002);
        spellPut("biao", -19990);
        spellPut("bie", -19986);
        spellPut("bin", -19982);
        spellPut("bing", -19976);
        spellPut("bo", -19805);
        spellPut("bu", -19784);
        spellPut("ca", -19775);
        spellPut("cai", -19774);
        spellPut("can", -19763);
        spellPut("cang", -19756);
        spellPut("cao", -19751);
        spellPut("ce", -19746);
        spellPut("ceng", -19741);
        spellPut("cha", -19739);
        spellPut("chai", -19728);
        spellPut("chan", -19725);
        spellPut("chang", -19715);
        spellPut("chao", -19540);
        spellPut("che", -19531);
        spellPut("chen", -19525);
        spellPut("cheng", -19515);
        spellPut("chi", -19500);
        spellPut("chong", -19484);
        spellPut("chou", -19479);
        spellPut("chu", -19467);
        spellPut("chuai", -19289);
        spellPut("chuan", -19288);
        spellPut("chuang", -19281);
        spellPut("chui", -19275);
        spellPut("chun", -19270);
        spellPut("chuo", -19263);
        spellPut("ci", -19261);
        spellPut("cong", -19249);
        spellPut("cou", -19243);
        spellPut("cu", -19242);
        spellPut("cuan", -19238);
        spellPut("cui", -19235);
        spellPut("cun", -19227);
        spellPut("cuo", -19224);
        spellPut("da", -19218);
        spellPut("dai", -19212);
        spellPut("dan", -19038);
        spellPut("dang", -19023);
        spellPut("dao", -19018);
        spellPut("de", -19006);
        spellPut("deng", -19003);
        spellPut("di", -18996);
        spellPut("dian", -18977);
        spellPut("diao", -18961);
        spellPut("die", -18952);
        spellPut("ding", -18783);
        spellPut("diu", -18774);
        spellPut("dong", -18773);
        spellPut("dou", -18763);
        spellPut("du", -18756);
        spellPut("duan", -18741);
        spellPut("dui", -18735);
        spellPut("dun", -18731);
        spellPut("duo", -18722);
        spellPut("e", -18710);
        spellPut("en", -18697);
        spellPut("er", -18696);
        spellPut("fa", -18526);
        spellPut("fan", -18518);
        spellPut("fang", -18501);
        spellPut("fei", -18490);
        spellPut("fen", -18478);
        spellPut("feng", -18463);
        spellPut("fo", -18448);
        spellPut("fou", -18447);
        spellPut("fu", -18446);
        spellPut("ga", -18239);
        spellPut("gai", -18237);
        spellPut("gan", -18231);
        spellPut("gang", -18220);
        spellPut("gao", -18211);
        spellPut("ge", -18201);
        spellPut("gei", -18184);
        spellPut("gen", -18183);
        spellPut("geng", -18181);
        spellPut("gong", -18012);
        spellPut("gou", -17997);
        spellPut("gu", -17988);
        spellPut("gua", -17970);
        spellPut("guai", -17964);
        spellPut("guan", -17961);
        spellPut("guang", -17950);
        spellPut("gui", -17947);
        spellPut("gun", -17931);
        spellPut("guo", -17928);
        spellPut("ha", -17922);
        spellPut("hai", -17759);
        spellPut("han", -17752);
        spellPut("hang", -17733);
        spellPut("hao", -17730);
        spellPut("he", -17721);
        spellPut("hei", -17703);
        spellPut("hen", -17701);
        spellPut("heng", -17697);
        spellPut("hong", -17692);
        spellPut("hou", -17683);
        spellPut("hu", -17676);
        spellPut("hua", -17496);
        spellPut("huai", -17487);
        spellPut("huan", -17482);
        spellPut("huang", -17468);
        spellPut("hui", -17454);
        spellPut("hun", -17433);
        spellPut("huo", -17427);
        spellPut("ji", -17417);
        spellPut("jia", -17202);
        spellPut("jian", -17185);
        spellPut("jiang", -16983);
        spellPut("jiao", -16970);
        spellPut("jie", -16942);
        spellPut("jin", -16915);
        spellPut("jing", -16733);
        spellPut("jiong", -16708);
        spellPut("jiu", -16706);
        spellPut("ju", -16689);
        spellPut("juan", -16664);
        spellPut("jue", -16657);
        spellPut("jun", -16647);
        spellPut("ka", -16474);
        spellPut("kai", -16470);
        spellPut("kan", -16465);
        spellPut("kang", -16459);
        spellPut("kao", -16452);
        spellPut("ke", -16448);
        spellPut("ken", -16433);
        spellPut("keng", -16429);
        spellPut("kong", -16427);
        spellPut("kou", -16423);
        spellPut("ku", -16419);
        spellPut("kua", -16412);
        spellPut("kuai", -16407);
        spellPut("kuan", -16403);
        spellPut("kuang", -16401);
        spellPut("kui", -16393);
        spellPut("kun", -16220);
        spellPut("kuo", -16216);
        spellPut("la", -16212);
        spellPut("lai", -16205);
        spellPut("lan", -16202);
        spellPut("lang", -16187);
        spellPut("lao", -16180);
        spellPut("le", -16171);
        spellPut("lei", -16169);
        spellPut("leng", -16158);
        spellPut("li", -16155);
        spellPut("lia", -15959);
        spellPut("lian", -15958);
        spellPut("liang", -15944);
        spellPut("liao", -15933);
        spellPut("lie", -15920);
        spellPut("lin", -15915);
        spellPut("ling", -15903);
        spellPut("liu", -15889);
        spellPut("long", -15878);
        spellPut("lou", -15707);
        spellPut("lu", -15701);
        spellPut("lv", -15681);
        spellPut("luan", -15667);
        spellPut("lue", -15661);
        spellPut("lun", -15659);
        spellPut("luo", -15652);
        spellPut("ma", -15640);
        spellPut("mai", -15631);
        spellPut("man", -15625);
        spellPut("mang", -15454);
        spellPut("mao", -15448);
        spellPut("me", -15436);
        spellPut("mei", -15435);
        spellPut("men", -15419);
        spellPut("meng", -15416);
        spellPut("mi", -15408);
        spellPut("mian", -15394);
        spellPut("miao", -15385);
        spellPut("mie", -15377);
        spellPut("min", -15375);
        spellPut("ming", -15369);
        spellPut("miu", -15363);
        spellPut("mo", -15362);
        spellPut("mou", -15183);
        spellPut("mu", -15180);
        spellPut("na", -15165);
        spellPut("nai", -15158);
        spellPut("nan", -15153);
        spellPut("nang", -15150);
        spellPut("nao", -15149);
        spellPut("ne", -15144);
        spellPut("nei", -15143);
        spellPut("nen", -15141);
        spellPut("neng", -15140);
        spellPut("ni", -15139);
        spellPut("nian", -15128);
        spellPut("niang", -15121);
        spellPut("niao", -15119);
        spellPut("nie", -15117);
        spellPut("nin", -15110);
        spellPut("ning", -15109);
        spellPut("niu", -14941);
        spellPut("nong", -14937);
        spellPut("nu", -14933);
        spellPut("nv", -14930);
        spellPut("nuan", -14929);
        spellPut("nue", -14928);
        spellPut("nuo", -14926);
        spellPut("o", -14922);
        spellPut("ou", -14921);
        spellPut("pa", -14914);
        spellPut("pai", -14908);
        spellPut("pan", -14902);
        spellPut("pang", -14894);
        spellPut("pao", -14889);
        spellPut("pei", -14882);
        spellPut("pen", -14873);
        spellPut("peng", -14871);
        spellPut("pi", -14857);
        spellPut("pian", -14678);
        spellPut("piao", -14674);
        spellPut("pie", -14670);
        spellPut("pin", -14668);
        spellPut("ping", -14663);
        spellPut("po", -14654);
        spellPut("pu", -14645);
        spellPut("qi", -14630);
        spellPut("qia", -14594);
        spellPut("qian", -14429);
        spellPut("qiang", -14407);
        spellPut("qiao", -14399);
        spellPut("qie", -14384);
        spellPut("qin", -14379);
        spellPut("qing", -14368);
        spellPut("qiong", -14355);
        spellPut("qiu", -14353);
        spellPut("qu", -14345);
        spellPut("quan", -14170);
        spellPut("que", -14159);
        spellPut("qun", -14151);
        spellPut("ran", -14149);
        spellPut("rang", -14145);
        spellPut("rao", -14140);
        spellPut("re", -14137);
        spellPut("ren", -14135);
        spellPut("reng", -14125);
        spellPut("ri", -14123);
        spellPut("rong", -14122);
        spellPut("rou", -14112);
        spellPut("ru", -14109);
        spellPut("ruan", -14099);
        spellPut("rui", -14097);
        spellPut("run", -14094);
        spellPut("ruo", -14092);
        spellPut("sa", -14090);
        spellPut("sai", -14087);
        spellPut("san", -14083);
        spellPut("sang", -13917);
        spellPut("sao", -13914);
        spellPut("se", -13910);
        spellPut("sen", -13907);
        spellPut("seng", -13906);
        spellPut("sha", -13905);
        spellPut("shai", -13896);
        spellPut("shan", -13894);
        spellPut("shang", -13878);
        spellPut("shao", -13870);
        spellPut("she", -13859);
        spellPut("shen", -13847);
        spellPut("sheng", -13831);
        spellPut("shi", -13658);
        spellPut("shou", -13611);
        spellPut("shu", -13601);
        spellPut("shua", -13406);
        spellPut("shuai", -13404);
        spellPut("shuan", -13400);
        spellPut("shuang", -13398);
        spellPut("shui", -13395);
        spellPut("shun", -13391);
        spellPut("shuo", -13387);
        spellPut("si", -13383);
        spellPut("song", -13367);
        spellPut("sou", -13359);
        spellPut("su", -13356);
        spellPut("suan", -13343);
        spellPut("sui", -13340);
        spellPut("sun", -13329);
        spellPut("suo", -13326);
        spellPut("ta", -13318);
        spellPut("tai", -13147);
        spellPut("tan", -13138);
        spellPut("tang", -13120);
        spellPut("tao", -13107);
        spellPut("te", -13096);
        spellPut("teng", -13095);
        spellPut("ti", -13091);
        spellPut("tian", -13076);
        spellPut("tiao", -13068);
        spellPut("tie", -13063);
        spellPut("ting", -13060);
        spellPut("tong", -12888);
        spellPut("tou", -12875);
        spellPut("tu", -12871);
        spellPut("tuan", -12860);
        spellPut("tui", -12858);
        spellPut("tun", -12852);
        spellPut("tuo", -12849);
        spellPut("wa", -12838);
        spellPut("wai", -12831);
        spellPut("wan", -12829);
        spellPut("wang", -12812);
        spellPut("wei", -12802);
        spellPut("wen", -12607);
        spellPut("weng", -12597);
        spellPut("wo", -12594);
        spellPut("wu", -12585);
        spellPut("xi", -12556);
        spellPut("xia", -12359);
        spellPut("xian", -12346);
        spellPut("xiang", -12320);
        spellPut("xiao", -12300);
        spellPut("xie", -12120);
        spellPut("xin", -12099);
        spellPut("xing", -12089);
        spellPut("xiong", -12074);
        spellPut("xiu", -12067);
        spellPut("xu", -12058);
        spellPut("xuan", -12039);
        spellPut("xue", -11867);
        spellPut("xun", -11861);
        spellPut("ya", -11847);
        spellPut("yan", -11831);
        spellPut("yang", -11798);
        spellPut("yao", -11781);
        spellPut("ye", -11604);
        spellPut("yi", -11589);
        spellPut("yin", -11536);
        spellPut("ying", -11358);
        spellPut("yo", -11340);
        spellPut("yong", -11339);
        spellPut("you", -11324);
        spellPut("yu", -11303);
        spellPut("yuan", -11097);
        spellPut("yue", -11077);
        spellPut("yun", -11067);
        spellPut("za", -11055);
        spellPut("zai", -11052);
        spellPut("zan", -11045);
        spellPut("zang", -11041);
        spellPut("zao", -11038);
        spellPut("ze", -11024);
        spellPut("zei", -11020);
        spellPut("zen", -11019);
        spellPut("zeng", -11018);
        spellPut("zha", -11014);
        spellPut("zhai", -10838);
        spellPut("zhan", -10832);
        spellPut("zhang", -10815);
        spellPut("zhao", -10800);
        spellPut("zhe", -10790);
        spellPut("zhen", -10780);
        spellPut("zheng", -10764);
        spellPut("zhi", -10587);
        spellPut("zhong", -10544);
        spellPut("zhou", -10533);
        spellPut("zhu", -10519);
        spellPut("zhua", -10331);
        spellPut("zhuai", -10329);
        spellPut("zhuan", -10328);
        spellPut("zhuang", -10322);
        spellPut("zhui", -10315);
        spellPut("zhun", -10309);
        spellPut("zhuo", -10307);
        spellPut("zi", -10296);
        spellPut("zong", -10281);
        spellPut("zou", -10274);
        spellPut("zu", -10270);
        spellPut("zuan", -10262);
        spellPut("zui", -10260);
        spellPut("zun", -10256);
        spellPut("zuo", -10254);
    }

    /**
     * 获得单个汉字的Ascii.
     *
     * @param cn char
     *           汉字字符
     * @return int
     * 错误返回 0,否则返回ascii
     */
    public static int getCnAscii(char cn) {
        byte[] bytes = null;
        try {
            bytes = (String.valueOf(cn)).getBytes("GBK");
        } catch (UnsupportedEncodingException ex) {
        }
        if (bytes == null || bytes.length > 2 || bytes.length <= 0) { //错误
            return 0;
        }
        if (bytes.length == 1) { //英文字符
            return bytes[0];
        }
        if (bytes.length == 2) { //中文字符
            int hightByte = 256 + bytes[0];
            int lowByte = 256 + bytes[1];

            int ascii = (256 * hightByte + lowByte) - 256 * 256;

            //System.out.println("ASCII=" + ascii);

            return ascii;
        }

        return 0; //错误
    }

    /**
     * 根据ASCII码到SpellMap中查找对应的拼音
     *
     * @param ascii int
     *              字符对应的ASCII
     * @return String
     * 拼音,首先判断ASCII是否>0&<160,如果是返回对应的字符,
     * <p/>
     * 否则到SpellMap中查找,如果没有找到拼音,则返回null,如果找到则返回拼音.
     */
    public static String getSpellByAscii(int ascii) {
        if (ascii > 0 && ascii < 160) { //单字符
            return String.valueOf((char) ascii);
        }

        if (ascii < -20319 || ascii > -10247) { //不知道的字符
            return null;
        }

        Set keySet = spellMap.keySet();
        Iterator it = keySet.iterator();

        String spell0 = null;
        String spell = null;

        int asciiRang0 = -20319;
        int asciiRang;
        while (it.hasNext()) {

            spell = (String) it.next();
            Object valObj = spellMap.get(spell);
            if (valObj instanceof Integer) {
                asciiRang = ((Integer) valObj).intValue();

                if (ascii >= asciiRang0 && ascii < asciiRang) { //区间找到
                    return (spell0 == null) ? spell : spell0;
                } else {
                    spell0 = spell;
                    asciiRang0 = asciiRang;
                }
            }
        }

        return null;

    }

    /**
     * 判断是否是字母
     *
     * @param ascii int
     * @return boolean
     */
    private static boolean isAlphabet(int ascii) {
        if (ascii > 0 && ascii < 160) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 返回字符串的全拼,是汉字转化为全拼,其它字符不进行转换
     *
     * @param cnStr String
     *              字符串
     * @return String
     * 转换成全拼后的字符串
     */
    public static String getFullSpell(String cnStr) {
        if (null == cnStr || "".equals(cnStr.trim())) {
            return cnStr;
        }

        boolean isChinese = false;

        char[] chars = cnStr.toCharArray();
        StringBuffer retuBuf = new StringBuffer();
        StringBuffer resultBuf = new StringBuffer();

        for (int i = 0, Len = chars.length; i < Len; i++) {
            int ascii = getCnAscii(chars[i]);
            if (ascii == 0) { //取ascii时出错
                retuBuf.append(chars[i]);
            } else {
                String spell = getSpellByAscii(ascii);
                if (spell == null) {
                    retuBuf.append(chars[i]);
                } else {
                    //System.out.println("spell:"+spell);
                    retuBuf.append(spell);

                } // end of if spell == null
                if (!isAlphabet(ascii)) {
                    isChinese = true;
                    retuBuf.append("");//这里可以添加文字间的间隔
                }
            } // end of if ascii <= -20400

        } // end of for
        if (isChinese) {
            //      resultBuf.append(cnStr);
            //      resultBuf.append("");
            resultBuf.append(retuBuf.toString());
        } else {
            resultBuf.append(retuBuf.toString());
        }
        return resultBuf.toString();

    }

    public static String getFirstSpell(String cnStr) {
        return null;
    }

    //  public static void main(String[] args) {
    //      String str = null;
    //
    //      try {
    //        str = new String("123".getBytes(), "GBK");
    //      }
    //      catch (UnsupportedEncodingException ex) {
    //      }
    //      System.out.println("Spell=" + CnToSpell.getFullSpell(str).toUpperCase().substring(0,1));
    //  }


}
  • 主Activity

public class MainActivity extends Activity {

    private TextView contact_show;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        contact_show = (TextView) findViewById(R.id.contact_show);
        Button contact_btn = (Button) findViewById(R.id.contact_btn);

        contact_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, ContactsActivity.class);
                startActivityForResult(intent, 2);
            }
        });
    }

    /**
     * 通讯录或二维码扫瞄回调事件
     */
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 2 && resultCode == 20) {// 通讯录导入结果
            contact_show.setText("姓名:"+data.getExtras().get("Name")+"\n号码:"+data.getExtras().get("phoneNumber"));
        }
    }
}
  • 主布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.getcontacts.MainActivity">


    <TextView
        android:id="@+id/contact_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="60dp"
        android:text="得到联系人姓名及电话"
        android:textSize="18sp"/>

    <Button
        android:id="@+id/contact_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/contact_show"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="60dp"
        android:text="点击获取联系人"
        />
</RelativeLayout>
  • 通讯录Activity
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import java.io.InputStream;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import util.ClearEditText;
import util.CnToSpell;
import util.MyListView;


public class ContactsActivity extends Activity {

    Context mContext = null;

    private ProgressDialog dialog;

    private static final int PROGRESSDIALOGID = 1;

    /**
     * 获取库Phon表字段
     **/
    private static final String[] PHONES_PROJECTION = new String[]{
            Phone.DISPLAY_NAME, Phone.NUMBER, Photo.PHOTO_ID, Phone.CONTACT_ID};

    /**
     * 联系人显示名称
     **/
    private static final int PHONES_DISPLAY_NAME_INDEX = 0;

    /**
     * 电话号码
     **/
    private static final int PHONES_NUMBER_INDEX = 1;

    /**
     * 头像ID
     **/
    private static final int PHONES_PHOTO_ID_INDEX = 2;

    /**
     * 联系人的ID
     **/
    private static final int PHONES_CONTACT_ID_INDEX = 3;

    private ArrayList<Map<String, Object>> items = new ArrayList<Map<String, Object>>();

    /**
     * 联系人名称
     **/
    private ArrayList<String> mContactsName = new ArrayList<String>();

    /**
     * 联系人号码
     **/
    private ArrayList<String> mContactsNumber = new ArrayList<String>();

    /**
     * 联系人头像
     **/
    private ArrayList<Bitmap> mContactsPhonto = new ArrayList<Bitmap>();

    private Handler handler;

    private BaseAdapter adapter;

    private OverlayThread overlayThread;
    private TextView overlay;
    private String[] sections;// 存放存在的汉语拼音首字母
    MyLetterListView letterListView = null;
    ListView mListView = null;
    private HashMap<String, Integer> alphaIndexer;// 存放存在的汉语拼音首字母和与之对应的列表位置
    private ClearEditText mClearEditText;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        mContext = this;
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_contacts);
        mClearEditText = (ClearEditText) findViewById(R.id.filter_edit);//可清除的EditText
        mListView = (ListView) findViewById(R.id.contact_list);
        letterListView = (MyListView) findViewById(R.id.ContactLetterListView);
        /** 得到手机通讯录联系人信息 **/
        getPhoneContacts();
        getSIMContacts();
        Comparator comp = new Mycomparator();
        Collections.sort(items, comp);
        //设置右侧触摸监听
        letterListView
                .setOnTouchingLetterChangedListener(new LetterListViewListener());
        alphaIndexer = new HashMap<String, Integer>();
        handler = new Handler();
        overlayThread = new OverlayThread();
        initOverlay();

        setAdapter(items);
        //根据输入框输入值的改变来过滤搜索
        mClearEditText.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) {

            }
        });

        mListView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> adapterView, View view,
                                    int position, long id) {
                // 调用系统方法拨打电话
                // Intent dialIntent = new Intent(Intent.ACTION_CALL, Uri
                // .parse("tel:" + mContactsNumber.get(position)));
                // startActivity(dialIntent);
                Map<String, Object> map = items.get(position);
                Intent intent = new Intent();
                intent.putExtra("Name", map.get("Name").toString());
                intent.putExtra("phoneNumber", map.get("phoneNumber")
                        .toString());
                setResult(20, intent);
                finish();
            }
        });

        super.onCreate(savedInstanceState);
    }

    /**
     * 根据输入框中的值来过滤数据并更新ListView
     *
     * @param filterStr
     */
    private void filterData(String filterStr) {
        List<Map<String, Object>> filterDateList = new ArrayList<Map<String, Object>>();
        if (TextUtils.isEmpty(filterStr)) {
            filterDateList = items;
        } else {
            filterDateList.clear();
            for (Map<String, Object> sortModel : items) {
                String name = (String) sortModel.get("Name");
                if (name.indexOf(filterStr.toString()) != -1 || CnToSpell.getFullSpell(name).startsWith(filterStr.toString())) {
                    filterDateList.add(sortModel);
                }
            }
        }

        // 根据a-z进行排序
        Comparator comp = new Mycomparator();
        Collections.sort(items, comp);
        setAdapter(filterDateList);
    }

    /**
     * 为ListView设置适配器
     *
     * @param list
     */
    private void setAdapter(List<Map<String, Object>> list) {
        if (list != null) {
            adapter = new ListAdapter(this, list);
            mListView.setAdapter(adapter);
        }

    }

    /**
     * ListViewAdapter
     */
    private class ListAdapter extends BaseAdapter {
        private LayoutInflater inflater;
        private List<Map<String, Object>> list;

        public ListAdapter(Context context, List<Map<String, Object>> list) {

            this.inflater = LayoutInflater.from(context);
            this.list = list;
            alphaIndexer = new HashMap<String, Integer>();
            sections = new String[list.size()];

            for (int i = 0; i < list.size(); i++) {
                // 当前汉语拼音首字母
                // getAlpha(list.get(i));
                String currentStr = list.get(i).get("Sort").toString();
                // 上一个汉语拼音首字母,如果不存在为“ ”
                String previewStr = (i - 1) >= 0 ? list.get(i - 1).get("Sort")
                        .toString() : " ";
                if (!previewStr.equals(currentStr)) {
                    String name = list.get(i).get("Sort").toString();
                    alphaIndexer.put(name, i);
                    sections[i] = name;
                }
            }

        }

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Object getItem(int position) {
            return list.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.clist_item, null);
                holder = new ViewHolder();
                holder.alpha = (TextView) convertView.findViewById(R.id.alpha);//
                holder.iamge = (ImageView) convertView.findViewById(R.id.image);
                holder.name = (TextView) convertView.findViewById(R.id.name);
                holder.phone = (TextView) convertView.findViewById(R.id.phone);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.iamge.setImageBitmap((Bitmap) (list.get(position)
                    .get("contactPhoto")));
            holder.name.setText(list.get(position).get("Name").toString());
            holder.phone.setText(list.get(position).get("phoneNumber")
                    .toString());
            String currentStr = list.get(position).get("Sort").toString();
            String previewStr = (position - 1) >= 0 ? list.get(position - 1)
                    .get("Sort").toString() : " ";
            if (!previewStr.equals(currentStr)) {
                holder.alpha.setVisibility(View.VISIBLE);
                holder.alpha.setText(currentStr);
            } else {
                holder.alpha.setVisibility(View.GONE);
            }
            return convertView;
        }

        private class ViewHolder {
            TextView alpha;
            ImageView iamge;
            TextView name;
            TextView phone;
        }

    }

    // 初始化汉语拼音首字母弹出提示框
    private void initOverlay() {
        LayoutInflater inflater = LayoutInflater.from(this);
        overlay = (TextView) inflater.inflate(R.layout.overlay, null);
        overlay.setVisibility(View.INVISIBLE);
        WindowManager.LayoutParams op = new WindowManager.LayoutParams();

        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
        WindowManager windowManager = (WindowManager) this
                .getSystemService(Context.WINDOW_SERVICE);
        windowManager.addView(overlay, lp);
    }

    private class LetterListViewListener implements
            MyLetterListView.OnTouchingLetterChangedListener {

        @Override
        public void onTouchingLetterChanged(final String s) {
            if (alphaIndexer.get(s) != null) {
                int position = alphaIndexer.get(s);
                mListView.setSelection(position);
                overlay.setText(sections[position]);
                overlay.setVisibility(View.VISIBLE);
                handler.removeCallbacks(overlayThread);
                // 延迟一秒后执行,让overlay为不可见
                handler.postDelayed(overlayThread, 1500);
            }
        }
    }

    // 设置overlay不可见
    private class OverlayThread implements Runnable {

        @Override
        public void run() {
            overlay.setVisibility(View.GONE);
        }

    }

    /**
     * 得到手机通讯录联系人信息
     **/
    private void getPhoneContacts() {
        this.showDialog(PROGRESSDIALOGID);

        ContentResolver resolver = mContext.getContentResolver();

        // 获取手机联系人
        Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,
                PHONES_PROJECTION, null, null, null);

        if (phoneCursor != null) {
            while (phoneCursor.moveToNext()) {
                Map<String, Object> map = new HashMap<String, Object>();

                // 得到联系人名称
                String contactName = phoneCursor
                        .getString(PHONES_DISPLAY_NAME_INDEX);

                String contactSort = CnToSpell.getFullSpell(contactName)
                        .toUpperCase().substring(0, 1);
                if (contactSort.equals("0") || contactSort.equals("1")
                        || contactSort.equals("2") || contactSort.equals("3")
                        || contactSort.equals("4") || contactSort.equals("5")
                        || contactSort.equals("6") || contactSort.equals("7")
                        || contactSort.equals("8") || contactSort.equals("9")) {
                    contactSort = "#";
                }

                // 得到手机号码
                String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX);
                // 当手机号码为空的或者为空字段 跳过当前循环
                if (TextUtils.isEmpty(phoneNumber))
                    continue;

                // 得到联系人ID
                Long contactid = phoneCursor.getLong(PHONES_CONTACT_ID_INDEX);

                // 得到联系人头像ID
                Long photoid = phoneCursor.getLong(PHONES_PHOTO_ID_INDEX);

                // 得到联系人头像Bitamp
                Bitmap contactPhoto = null;

                // photoid 大于0 表示联系人有头像 如果没有给此人设置头像则给他一个默认的
                if (photoid > 0) {
                    Uri uri = ContentUris.withAppendedId(
                            ContactsContract.Contacts.CONTENT_URI, contactid);
                    InputStream input = ContactsContract.Contacts
                            .openContactPhotoInputStream(resolver, uri);
                    contactPhoto = BitmapFactory.decodeStream(input);
                } else {
                    contactPhoto = BitmapFactory.decodeResource(getResources(),
                            R.mipmap.contact_photo);
                }

                map.put("Name", contactName);
                map.put("phoneNumber", phoneNumber);
                map.put("contactPhoto", contactPhoto);
                map.put("Sort", contactSort);

                // mContactsName.add(contactName);
                // mContactsNumber.add(phoneNumber);
                // mContactsPhonto.add(contactPhoto);
                items.add(map);
            }

            dismissDialog(PROGRESSDIALOGID);
            phoneCursor.close();
        }
    }

    // 通讯社按中文拼音排序
    public class Mycomparator implements Comparator {
        public int compare(Object o1, Object o2) {
            Map<String, Object> c1 = (Map<String, Object>) o1;
            Map<String, Object> c2 = (Map<String, Object>) o2;
            Comparator cmp = Collator.getInstance(java.util.Locale.ENGLISH);
            return cmp.compare(c1.get("Sort"), c2.get("Sort"));
        }
    }

    /**
     * 得到手机SIM卡联系人人信息
     **/
    private void getSIMContacts() {
        ContentResolver resolver = mContext.getContentResolver();
        // 获取Sims卡联系人
        Uri uri = Uri.parse("content://icc/adn");
        Cursor phoneCursor = resolver.query(uri, PHONES_PROJECTION, null, null,
                null);

        if (phoneCursor != null) {
            while (phoneCursor.moveToNext()) {
                Map<String, Object> map = new HashMap<String, Object>();
                // 得到手机号码
                String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX);
                // 当手机号码为空的或者为空字段 跳过当前循环
                if (TextUtils.isEmpty(phoneNumber))
                    continue;
                // 得到联系人名称
                String contactName = phoneCursor
                        .getString(PHONES_DISPLAY_NAME_INDEX);
                String contactSort = CnToSpell.getFullSpell(contactName)
                        .toUpperCase().substring(0, 1);
                if (contactSort.equals("0") || contactSort.equals("1")
                        || contactSort.equals("2") || contactSort.equals("3")
                        || contactSort.equals("4") || contactSort.equals("5")
                        || contactSort.equals("6") || contactSort.equals("7")
                        || contactSort.equals("8") || contactSort.equals("9")) {
                    contactSort = "#";
                }

                Bitmap contactPhoto = null;
                // Sim卡中没有联系人头像,使用默认的
                contactPhoto = BitmapFactory.decodeResource(getResources(),
                        R.mipmap.contact_photo);

                map.put("Name", contactName);
                map.put("phoneNumber", phoneNumber);
                map.put("contactPhoto", contactPhoto);
                map.put("Sort", contactSort);
                items.add(map);
            }

            phoneCursor.close();
        }
    }

}
  • 通讯录布局
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:background="#fff"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <util...EditText
        android:id="@+id/filter_edit"
        android:layout_width="fill_parent"
        android:layout_height="35dp"
        android:layout_margin="5dip"
        android:background="@drawable/search_bar_edit_selector"
        android:drawableLeft="@mipmap/search_bar_icon_normal"
        android:hint="请输入关键字"
        android:paddingLeft="6dp"
        android:paddingRight="6dp"
        android:singleLine="true"
        android:textSize="15.0dip"/>

    <RelativeLayout
        android:id="@+id/contact_layout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginTop="2dp"
        android:orientation="vertical">

        <ListView
            android:id="@+id/contact_list"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="#fff"
            android:cacheColorHint="#00000000"
            android:scrollbars="none"/>



        <util....ListView
            android:id="@+id/ContactLetterListView"
            android:layout_width="30dip"
            android:layout_height="fill_parent"
            android:layout_alignParentRight="true"
            android:layout_marginBottom="2dp"
            />
    </RelativeLayout>

</LinearLayout>



  • 联系人的item 布局
<?xml version="1.0" encoding="utf-8"?>
<!--联系人的item-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginBottom="5dp">

    <TextView
        android:id="@+id/alpha"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#ebf0f0"
        android:paddingLeft="13dip"
        android:textAppearance="?android:textAppearanceMedium"
        android:textColor="#0b0306"
        android:visibility="gone"
        />

    <ImageView
        android:id="@+id/image"
        android:layout_width="50dip"
        android:layout_height="50dip"
        android:layout_below="@id/alpha"
        android:layout_marginBottom="5dp"
        android:layout_marginTop="5dp"
        android:src="@mipmap/contact_photo"/>

    <TextView
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@id/alpha"
        android:layout_marginLeft="5.0dip"
        android:layout_marginTop="5dp"
        android:layout_toRightOf="@+id/image"
        android:singleLine="true"
        android:text="姓名"
        android:textSize="20dip"/>

    <TextView
        android:id="@+id/phone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/name"
        android:layout_marginBottom="5dp"
        android:layout_marginLeft="5.0dip"
        android:layout_toRightOf="@+id/image"
        android:singleLine="true"
        android:text="电话"
        android:textSize="20dip"/>

</RelativeLayout>
  • 滑动首字母提示布局
<?xml version="1.0" encoding="utf-8"?>
<!--弹出首字母的提示框-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="40dp"
          android:layout_height="23dp"
          android:background="@drawable/shape_bule_overly"
          android:gravity="center"
          android:maxWidth="80dip"
          android:minWidth="80dip"
          android:padding="5dip"
          android:text="k"
          android:textColor="#fff"
          android:textSize="53sp"/>

代码完毕

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值