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

Android手机联系人带字母索引的快速查找

程序员文章站 2024-03-31 12:55:04
喜欢另辟蹊径的我,在这里废话不多说了,直接上代码和图片了。 效果图如下: 第一步:mainactivity的代码如下: package net.loo...

喜欢另辟蹊径的我,在这里废话不多说了,直接上代码和图片了。
效果图如下:

Android手机联系人带字母索引的快速查找

第一步:mainactivity的代码如下:

package net.loonggg.test; 
 
import java.util.arraylist; 
import java.util.arrays; 
import java.util.hashmap; 
import java.util.list; 
import java.util.treeset; 
 
import android.os.bundle; 
import android.app.activity; 
import android.graphics.color; 
import android.view.motionevent; 
import android.view.view; 
import android.view.view.ontouchlistener; 
import android.view.window; 
import android.widget.linearlayout; 
import android.widget.listview; 
import android.widget.textview; 
import android.widget.linearlayout.layoutparams; 
 
public class mainactivity extends activity { 
  private hashmap<string, integer> selector;// 存放含有索引字母的位置 
  private linearlayout layoutindex; 
  private listview listview; 
  private textview tv_show; 
  private listviewadapter adapter; 
  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" }; 
  private list<person> persons = null; 
  private list<person> newpersons = new arraylist<person>(); 
  private int height;// 字体高度 
  private boolean flag = false; 
 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
    // 去标题栏 
    requestwindowfeature(window.feature_no_title); 
    setcontentview(r.layout.activity_main); 
    layoutindex = (linearlayout) this.findviewbyid(r.id.layout); 
    layoutindex.setbackgroundcolor(color.parsecolor("#00ffffff")); 
    listview = (listview) findviewbyid(r.id.listview); 
    tv_show = (textview) findviewbyid(r.id.tv); 
    tv_show.setvisibility(view.gone); 
    setdata(); 
    string[] allnames = sortindex(persons); 
    sortlist(allnames); 
 
    selector = new hashmap<string, integer>(); 
    for (int j = 0; j < indexstr.length; j++) {// 循环字母表,找出newpersons中对应字母的位置 
      for (int i = 0; i < newpersons.size(); i++) { 
        if (newpersons.get(i).getname().equals(indexstr[j])) { 
          selector.put(indexstr[j], i); 
        } 
      } 
 
    } 
    adapter = new listviewadapter(this, newpersons); 
    listview.setadapter(adapter); 
  } 
 
  /** 
   * 重新排序获得一个新的list集合 
   * 
   * @param allnames 
   */ 
  private void sortlist(string[] allnames) { 
    for (int i = 0; i < allnames.length; i++) { 
      if (allnames[i].length() != 1) { 
        for (int j = 0; j < persons.size(); j++) { 
          if (allnames[i].equals(persons.get(j).getpinyinname())) { 
            person p = new person(persons.get(j).getname(), persons 
                .get(j).getpinyinname()); 
            newpersons.add(p); 
          } 
        } 
      } else { 
        newpersons.add(new person(allnames[i])); 
      } 
    } 
  } 
 
  @override 
  public void onwindowfocuschanged(boolean hasfocus) { 
    // 在oncreate里面执行下面的代码没反应,因为oncreate里面得到的getheight=0 
    if (!flag) {// 这里为什么要设置个flag进行标记,我这里不先告诉你们,请读者研究,因为这对你们以后的开发有好处 
      height = layoutindex.getmeasuredheight() / indexstr.length; 
      getindexview(); 
      flag = true; 
    } 
  } 
 
  /** 
   * 获取排序后的新数据 
   * 
   * @param persons 
   * @return 
   */ 
  public string[] sortindex(list<person> persons) { 
    treeset<string> set = new treeset<string>(); 
    // 获取初始化数据源中的首字母,添加到set中 
    for (person person : persons) { 
      set.add(stringhelper.getpinyinheadchar(person.getname()).substring( 
          0, 1)); 
    } 
    // 新数组的长度为原数据加上set的大小 
    string[] names = new string[persons.size() + set.size()]; 
    int i = 0; 
    for (string string : set) { 
      names[i] = string; 
      i++; 
    } 
    string[] pinyinnames = new string[persons.size()]; 
    for (int j = 0; j < persons.size(); j++) { 
      persons.get(j).setpinyinname( 
          stringhelper 
              .getpingyin(persons.get(j).getname().tostring())); 
      pinyinnames[j] = stringhelper.getpingyin(persons.get(j).getname() 
          .tostring()); 
    } 
    // 将原数据拷贝到新数据中 
    system.arraycopy(pinyinnames, 0, names, set.size(), pinyinnames.length); 
    // 自动按照首字母排序 
    arrays.sort(names, string.case_insensitive_order); 
    return names; 
  } 
 
  /** 
   * 绘制索引列表 
   */ 
  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("#606060")); 
            break; 
 
          case motionevent.action_move: 
 
            break; 
          case motionevent.action_up: 
            layoutindex.setbackgroundcolor(color 
                .parsecolor("#00ffffff")); 
            tv_show.setvisibility(view.gone); 
            break; 
          } 
          return true; 
        } 
      }); 
    } 
  } 
 
  /** 
   * 设置模拟数据 
   */ 
  private void setdata() { 
    persons = new arraylist<person>(); 
    person p1 = new person("耿琦"); 
    persons.add(p1); 
    person p2 = new person("王宝强"); 
    persons.add(p2); 
    person p3 = new person("柳岩"); 
    persons.add(p3); 
    person p4 = new person("文章"); 
    persons.add(p4); 
    person p5 = new person("马伊琍"); 
    persons.add(p5); 
    person p6 = new person("李晨"); 
    persons.add(p6); 
    person p7 = new person("张馨予"); 
    persons.add(p7); 
    person p8 = new person("韩红"); 
    persons.add(p8); 
    person p9 = new person("韩寒"); 
    persons.add(p9); 
    person p10 = new person("丹丹"); 
    persons.add(p10); 
    person p11 = new person("丹凤眼"); 
    persons.add(p11); 
    person p12 = new person("哈哈"); 
    persons.add(p12); 
    person p13 = new person("萌萌"); 
    persons.add(p13); 
    person p14 = new person("蒙混"); 
    persons.add(p14); 
    person p15 = new person("烟花"); 
    persons.add(p15); 
    person p16 = new person("眼黑"); 
    persons.add(p16); 
    person p17 = new person("许三多"); 
    persons.add(p17); 
    person p18 = new person("程咬金"); 
    persons.add(p18); 
    person p19 = new person("程哈哈"); 
    persons.add(p19); 
    person p20 = new person("爱死你"); 
    persons.add(p20); 
    person p21 = new person("阿莱"); 
    persons.add(p21); 
 
  } 
 
}

 此activity的布局文件如下:

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="match_parent" 
  android:background="#ffffff" 
  android:orientation="vertical" > 
 
  <textview 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:padding="10dp" 
    android:text="列表显示" 
    android:textcolor="#000000" 
    android:textsize="16sp" /> 
 
  <framelayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#ffffff" > 
 
    <listview 
      android:id="@+id/listview" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:cachecolorhint="#00000000" 
      android:fadingedge="none" 
      android:scrollbars="none" > 
    </listview> 
 
    <textview 
      android:id="@+id/tv" 
      android:layout_width="60dp" 
      android:layout_height="60dp" 
      android:layout_gravity="center" 
      android:background="#f0606060" 
      android:gravity="center" 
      android:text="a" 
      android:textcolor="#ffffff" 
      android:textsize="30sp" /> 
 
    <linearlayout 
      android:id="@+id/layout" 
      android:layout_width="wrap_content" 
      android:layout_height="fill_parent" 
      android:layout_gravity="right" 
      android:background="#d7d7d7" 
      android:gravity="center" 
      android:orientation="vertical" > 
    </linearlayout> 
  </framelayout> 
 
</linearlayout> 

第二步:自定义了一个adapter,代码如下:

package net.loonggg.test; 
 
import java.util.list; 
 
import android.content.context; 
import android.view.layoutinflater; 
import android.view.view; 
import android.view.viewgroup; 
import android.widget.baseadapter; 
import android.widget.textview; 
 
public class listviewadapter extends baseadapter { 
  private context context; 
  private list<person> list; 
  private viewholder viewholder; 
 
  public listviewadapter(context context, list<person> list) { 
    this.context = context; 
    this.list = list; 
  } 
 
  @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 boolean isenabled(int position) { 
    // todo auto-generated method stub 
    if (list.get(position).getname().length() == 1)// 如果是字母索引 
      return false;// 表示不能点击 
    return super.isenabled(position); 
  } 
 
  @override 
  public view getview(int position, view convertview, viewgroup parent) { 
    string item = list.get(position).getname(); 
    viewholder = new viewholder(); 
    if (item.length() == 1) { 
      convertview = layoutinflater.from(context).inflate(r.layout.index, 
          null); 
      viewholder.indextv = (textview) convertview 
          .findviewbyid(r.id.indextv); 
    } else { 
      convertview = layoutinflater.from(context).inflate(r.layout.item, 
          null); 
      viewholder.itemtv = (textview) convertview 
          .findviewbyid(r.id.itemtv); 
    } 
    if (item.length() == 1) { 
      viewholder.indextv.settext(list.get(position).getname()); 
    } else { 
      viewholder.itemtv.settext(list.get(position).getname()); 
    } 
    return convertview; 
  } 
 
  private class viewholder { 
    private textview indextv; 
    private textview itemtv; 
  } 
 
} 

第三步:用到的listview中的子布局文件如下:
1、index.xml布局文件代码如下:

<?xml version="1.0" encoding="utf-8"?> 
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:background="#9c9c9c" 
  android:orientation="vertical" 
  android:paddingbottom="5dp" 
  android:paddingleft="10dp" 
  android:paddingtop="5dp" > 
 
  <textview 
    android:id="@+id/indextv" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textcolor="#0f0f0f" /> 
 
</linearlayout> 

2、item.xml布局文件代码如下:

<?xml version="1.0" encoding="utf-8"?> 
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:background="#ffffff" 
  android:orientation="vertical" 
  android:paddingbottom="5dp" 
  android:paddingleft="20dp" 
  android:paddingtop="5dp" > 
 
  <textview 
    android:id="@+id/itemtv" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textcolor="#000000" 
    android:textsize="20sp" /> 
 
</linearlayout> 

第四步:用到的实体类及工具类如下:
1、person.java代码如下:

package net.loonggg.test; 
 
public class person { 
  private string name; 
  private string pinyinname; 
 
  public person(string name) { 
    super(); 
    this.name = name; 
  } 
 
  public person(string name, string pinyinname) { 
    super(); 
    this.name = name; 
    this.pinyinname = pinyinname; 
  } 
 
  public string getname() { 
    return name; 
  } 
 
  public void setname(string name) { 
    this.name = name; 
  } 
 
  public string getpinyinname() { 
    return pinyinname; 
  } 
 
  public void setpinyinname(string pinyinname) { 
    this.pinyinname = pinyinname; 
  } 
 
} 

2、工具类代码如下:

package net.loonggg.test; 
 
import net.sourceforge.pinyin4j.pinyinhelper; 
import net.sourceforge.pinyin4j.format.hanyupinyincasetype; 
import net.sourceforge.pinyin4j.format.hanyupinyinoutputformat; 
import net.sourceforge.pinyin4j.format.hanyupinyintonetype; 
import net.sourceforge.pinyin4j.format.hanyupinyinvchartype; 
import net.sourceforge.pinyin4j.format.exception.badhanyupinyinoutputformatcombination; 
 
public class stringhelper { 
  /** 
   * 得到 全拼 
   * 
   * @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 getheadchar(string str) { 
 
    string convert = ""; 
    char word = str.charat(0); 
    string[] pinyinarray = pinyinhelper.tohanyupinyinstringarray(word); 
    if (pinyinarray != null) { 
      convert += pinyinarray[0].charat(0); 
    } else { 
      convert += word; 
    } 
    return convert.touppercase(); 
  } 
   
  /** 
   * 得到中文首字母缩写 
   * 
   * @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(); 
  } 
} 

到这里就完事,非常简单吧!