Android手机联系人快速索引(手机通讯录)
程序员文章站
2023-12-18 18:28:34
最近需要实现一个手机通讯录的快速索引功能。根据姓名首字母快速索引功能。下面是一个手机联系人快速索引的效果,总体来说代码不算难,拼音转换的地方略有复杂。下面上源码:源码中有注...
最近需要实现一个手机通讯录的快速索引功能。根据姓名首字母快速索引功能。下面是一个手机联系人快速索引的效果,总体来说代码不算难,拼音转换的地方略有复杂。下面上源码:源码中有注释。
下面是效果图:
mainactivity:
import java.util.arraylist; import java.util.collections; import java.util.list; import android.app.activity; import android.os.bundle; import android.os.handler; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.listview; import android.widget.textview; /** * 这里是主布局 * @author lxd * */ public class mainactivity extends activity { private listview lv_main; private friendadapter adapter; private list<friend> data = new arraylist<friend>(); private quickindexview qiv_main; private textview tv_main_word; private handler handler = new handler(){ public void handlemessage(android.os.message msg) { //隐藏word tv_main_word.setvisibility(view.gone); } }; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); lv_main = (listview) findviewbyid(r.id.lv_main); qiv_main = (quickindexview) findviewbyid(r.id.qiv_main); tv_main_word = (textview) findviewbyid(r.id.tv_main_word); //设置监听 qiv_main.setonindexchangedlistener(new quickindexview.onindexchangedlistener() { @override public void onindexchanged(string word) { tv_main_word.settext(word); tv_main_word.setvisibility(view.visible); //handler.removemessages(1); //移除未处理的消息 handler.removecallbacksandmessages(null); //发延迟消息 handler.sendemptymessagedelayed(1, 2000); //滑动listview //查找对应的item for(int i=0;i<data.size();i++) { string fword = data.get(i).getpinyin().substring(0, 1); if(word.equals(fword)) { lv_main.setselection(i); return; } } } @override public void onup() { //tv_main_word.setvisibility(view.gone); } }); //显示列表 adapter = new friendadapter(); initdata(); lv_main.setadapter(adapter); //lv_main.setselection(5); } private void initdata() { data.add(new friend("张三")); data.add(new friend("杨九")); data.add(new friend("胡继群")); data.add(new friend("刘畅")); data.add(new friend("钟泽兴")); data.add(new friend("尹革新")); data.add(new friend("安传鑫")); data.add(new friend("张骞壬")); data.add(new friend("温松")); data.add(new friend("李凤秋")); data.add(new friend("刘甫")); data.add(new friend("娄全超")); data.add(new friend("张猛")); data.add(new friend("王英杰")); data.add(new friend("李振南")); data.add(new friend("孙仁政")); data.add(new friend("唐春雷")); data.add(new friend("牛鹏伟")); data.add(new friend("姜宇航")); data.add(new friend("刘挺")); data.add(new friend("张洪瑞")); data.add(new friend("张建忠")); data.add(new friend("侯亚帅")); data.add(new friend("刘帅")); data.add(new friend("乔竞飞")); data.add(new friend("徐雨健")); data.add(new friend("吴亮")); data.add(new friend("王兆霖")); data.add(new friend("阿三")); collections.sort(data); } class friendadapter extends baseadapter { @override public int getcount() { return data.size(); } @override public object getitem(int position) { return data.get(position); } @override public long getitemid(int position) { return 0; } @override public view getview(int position, view convertview, viewgroup parent) { viewholder holder = null; if(convertview==null) { holder = new viewholder(); convertview = view.inflate(mainactivity.this, r.layout.item_main, null); holder.wordtv = (textview) convertview.findviewbyid(r.id.tv_item_word); holder.nametv = (textview) convertview.findviewbyid(r.id.tv_item_name); convertview.settag(holder);//***********? } else { holder = (viewholder) convertview.gettag(); } friend friend = data.get(position); string word = friend.getpinyin().substring(0, 1); holder.wordtv.settext(word); holder.nametv.settext(friend.getname()); //下标为0的显示 if(position==0) { holder.wordtv.setvisibility(view.visible); } else { //取出上一个friend, 并得到的第一个word string preword = data.get(position-1).getpinyin().substring(0, 1); //判断是否于当前行的word是否相同 //如果相同, 隐藏 if(word.equals(preword)) { holder.wordtv.setvisibility(view.gone); } else { //如果不同, 显示 holder.wordtv.setvisibility(view.visible); } } return convertview; } class viewholder { public textview wordtv; public textview nametv; } } }
主布局:
<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="${relativepackage}.${activityclass}" > <listview android:id="@+id/lv_main" android:layout_width="match_parent" android:layout_height="match_parent" > </listview> <!-- com.atguigu.quickindex.quickindexview --> <com.atguigu.quickindex.quickindexview android:id="@+id/qiv_main" android:layout_width="40dp" android:layout_height="match_parent" android:layout_alignparentright="true" android:background="#ffffff" > </com.atguigu.quickindex.quickindexview> <textview android:id="@+id/tv_main_word" android:layout_width="100dp" android:layout_height="100dp" android:layout_centerhorizontal="true" android:layout_centervertical="true" android:background="#66666666" android:text="a" android:textsize="40sp" android:gravity="center" android:visibility="gone"/> </relativelayout>
item:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <textview android:id="@+id/tv_item_word" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="a" android:background="#66666666" android:textsize="18sp" android:padding="5dp"/> <textview android:id="@+id/tv_item_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="某人" android:textsize="18sp" android:padding="5dp"/> </linearlayout>
自定义view:
import android.content.context; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.rect; import android.util.attributeset; import android.view.motionevent; import android.view.view; /** * 这里是自定义view * @author lxd * */ public class quickindexview extends view { private float itemwidth; private float itemheight; // private float wordwidth; // private float wordheight; private string[] indexarr = { "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 paint paint; public quickindexview(context context, attributeset attrs) { super(context, attrs); paint = new paint(); paint.setcolor(color.white); paint.settextsize(16); paint.setantialias(true); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); itemwidth = this.getmeasuredwidth(); itemheight = this.getmeasuredheight() / 26f; } @override protected void ondraw(canvas canvas) { //当每次触发重绘的时候,就把26个字母循环一遍 for (int i = 0; i < indexarr.length; i++) { string word = indexarr[i]; // 设置文字的颜色 if (i == touchindex) { //这里设置被点击的字母变化:颜色变灰色、字体变25sp paint.setcolor(color.gray); paint.settextsize(25); } else { //其他没被点击的字母,保持原有状态:设置颜色、字体大小为18sp paint.setcolor(color.black); paint.settextsize(18); } // 得到word的宽高 rect bounds = new rect(); paint.gettextbounds(word, 0, word.length(), bounds); //得到字体的宽 int wordwidth = bounds.width(); //得到字体的高 int wordheight = bounds.height(); // 计算word的左上角的坐标:字母所在的x坐标、y坐标 float x = itemwidth / 2 - wordwidth / 2; float y = itemheight / 2 + wordheight / 2 + i * itemheight; // 绘制word canvas.drawtext(word, x, y, paint); } } // /////////////////////////////////////////////////////////////////////// private int touchindex = -1;// 触摸的字母的下标 @override public boolean ontouchevent(motionevent event) { // 得到事件坐标 float eventy = event.gety(); switch (event.getaction()) { case motionevent.action_down: case motionevent.action_move: // 计算下标 int index = (int) (eventy / itemheight); if (index > 25) { index = 25; } if (index < 0) { index = 0; } // 如果下标有改变, 强制重绘 if (index != touchindex) { // 更新touchindex touchindex = index; // 强制重绘 invalidate(); // 通知activity更新textview if (onindexchangedlistener != null) { onindexchangedlistener.onindexchanged(indexarr[index]); } } break; case motionevent.action_up: touchindex = -1; // 强制重绘 invalidate(); // 通知activity更新textview if (onindexchangedlistener != null) { onindexchangedlistener.onup(); } break; default: break; } return true;// 所有的事件都由当前视图消费 } private onindexchangedlistener onindexchangedlistener; /* * 设置监听对象的方法 这个方法一般是activity调用 */ public void setonindexchangedlistener( onindexchangedlistener onindexchangedlistener) { this.onindexchangedlistener = onindexchangedlistener; } interface onindexchangedlistener { // 当操作的下标改变时自动调用 public void onindexchanged(string word); // 当up时调用 public void onup(); } }
联系人类:
/** * 联系人类 * @author lxd * */ public class friend implements comparable<friend> { private string name; private string pinyin; public friend(string name) { super(); this.name = name; pinyin = pinyinutils.getpinyin(name); } public string getname() { return name; } public void setname(string name) { this.name = name; } public string getpinyin() { return pinyin; } public void setpinyin(string pinyin) { this.pinyin = pinyin; } @override public string tostring() { return "friend [name=" + name + ", pinyin=" + pinyin + "]"; } @override public int compareto(friend another) { return this.pinyin.compareto(another.getpinyin()); } }
工具类:用于将汉字转换为拼音
/** * 将汉字转换为拼音 * @author lxd * */ public class pinyinutils { /** * 得到指定汉字的拼音 * 注意:不应该被频繁调用,它消耗一定内存 * @param hanzi * @return */ public static string getpinyin(string hanzi){ string pinyin = ""; hanyupinyinoutputformat format = new hanyupinyinoutputformat();//控制转换是否大小写,是否带音标 format.setcasetype(hanyupinyincasetype.uppercase);//大写 format.settonetype(hanyupinyintonetype.without_tone); //由于不能直接对多个汉字转换,只能对单个汉字转换 char[] arr = hanzi.tochararray(); for (int i = 0; i < arr.length; i++) { if(character.iswhitespace(arr[i]))continue;//如果是空格,则不处理,进行下次遍历 //汉字是2个字节存储,肯定大于127,所以大于127就可以当为汉字转换 if(arr[i]>127){ try { //由于多音字的存在,单 dan shan string[] pinyinarr = pinyinhelper.tohanyupinyinstringarray(arr[i], format); if(pinyinarr!=null){ pinyin += pinyinarr[0]; }else { pinyin += arr[i]; } } catch (badhanyupinyinoutputformatcombination e) { e.printstacktrace(); //不是正确的汉字 pinyin += arr[i]; } }else { //不是汉字, pinyin += arr[i]; } } return pinyin; } }
以上代码是关于android手机联系人快速索引(手机通讯录)的全部叙述,希望大家喜欢。