转载请注明出处:http://blog.csdn.net/xiaanming/article/details/12684155
前段时间因为换工作的缘故又恰巧碰到国庆节,所以有段时间自己没有更新博客了,过完国庆到新公司报道,感觉还不错,就是现在住的地方离新公司有点远,地铁20站,伤不起啊,我每天早上7点多就要起床,然后屁颠屁颠的去挤地铁上班,晚上下班还要挤地铁,先不说路程远,车费一天就要10几块,我的银子啊,有坐龙华线去上班的深圳程序员不?听说那条线上班高峰期很挤?我没在上班高峰期坐过那趟车,我在民治那边找了个房子,离华强北也不远,关键房租便宜,哈哈,乐开花了,下个礼拜就要搬过去啦
不扯了,回到主题,今天给大家带来ListView的A-Z字母排序和过滤搜索功能并且实现汉字转成拼音的功能,我们知道一般我们对联系人,城市列表等实现A-Z的排序,因为联系人和城市列表我们可以直接从数据库中获取他的汉字拼音,而对于一般的数据,我们怎么实现A-Z的排序,我们需要将汉字转换成拼音就行了,接下来就带大家实现一般数据的A-Z排序功能,首先先看下效果图
上面是一个带删除按钮的EditText,我们在输入框中输入可以自动过滤出我们想要的东西,当输入框中没有数据自动替换到原来的数据列表,然后下面一个ListView用来显示数据列表,右侧是一个字母索引表,当我们点击不同的字母,ListView会定位到该字母地方,了解了布局之后,我们先看下项目结构吧
我按照项目中类的顺序来一一介绍其功能
1.SortModel 一个实体类,里面一个是ListView的name,另一个就是显示的name拼音的首字母
- packagecom.example.sortlistview;
-
- publicclassSortModel{
-
- privateStringname;
- privateStringsortLetters;
-
- publicStringgetName(){
- returnname;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- publicStringgetSortLetters(){
- returnsortLetters;
- }
- publicvoidsetSortLetters(StringsortLetters){
- this.sortLetters=sortLetters;
- }
- }
2.SideBar类就是ListView右侧的字母索引View,我们需要使用setTextView(TextView mTextDialog)来设置用来显示当前按下的字母的TextView,以及使用setOnTouchingLetterChangedListener方法来设置回调接口,在回调方法onTouchingLetterChanged(String s)中来处理不同的操作
- packagecom.example.sortlistview;
-
- importandroid.content.Context;
- importandroid.graphics.Canvas;
- importandroid.graphics.Color;
- importandroid.graphics.Paint;
- importandroid.graphics.Typeface;
- importandroid.graphics.drawable.ColorDrawable;
- importandroid.util.AttributeSet;
- importandroid.view.MotionEvent;
- importandroid.view.View;
- importandroid.widget.TextView;
-
- publicclassSideBarextendsView{
-
- privateOnTouchingLetterChangedListeneronTouchingLetterChangedListener;
-
- publicstaticString[]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","#"};
- privateintchoose=-1;
- privatePaintpaint=newPaint();
-
- privateTextViewmTextDialog;
-
-
-
-
-
- publicvoidsetTextView(TextViewmTextDialog){
- this.mTextDialog=mTextDialog;
- }
-
-
- publicSideBar(Contextcontext,AttributeSetattrs,intdefStyle){
- super(context,attrs,defStyle);
- }
-
- publicSideBar(Contextcontext,AttributeSetattrs){
- super(context,attrs);
- }
-
- publicSideBar(Contextcontext){
- super(context);
- }
-
-
-
-
- protectedvoidonDraw(Canvascanvas){
- super.onDraw(canvas);
-
- intheight=getHeight();
- intwidth=getWidth();
- intsingleHeight=height/b.length;
-
- for(inti=0;i<b.length;i++){
- paint.setColor(Color.rgb(33,65,98));
-
- paint.setTypeface(Typeface.DEFAULT_BOLD);
- paint.setAntiAlias(true);
- paint.setTextSize(20);
-
- if(i==choose){
- paint.setColor(Color.parseColor("#3399ff"));
- paint.setFakeBoldText(true);
- }
-
- floatxPos=width/2-paint.measureText(b[i])/2;
- floatyPos=singleHeight*i+singleHeight;
- canvas.drawText(b[i],xPos,yPos,paint);
- paint.reset();
- }
-
- }
-
- @Override
- publicbooleandispatchTouchEvent(MotionEventevent){
- finalintaction=event.getAction();
- finalfloaty=event.getY();
- finalintoldChoose=choose;
- finalOnTouchingLetterChangedListenerlistener=onTouchingLetterChangedListener;
- finalintc=(int)(y/getHeight()*b.length);
-
- switch(action){
- caseMotionEvent.ACTION_UP:
- setBackgroundDrawable(newColorDrawable(0x00000000));
- choose=-1;
- invalidate();
- if(mTextDialog!=null){
- mTextDialog.setVisibility(View.INVISIBLE);
- }
- break;
-
- default:
- setBackgroundResource(R.drawable.sidebar_background);
- if(oldChoose!=c){
- if(c>=0&&c<b.length){
- if(listener!=null){
- listener.onTouchingLetterChanged(b[c]);
- }
- if(mTextDialog!=null){
- mTextDialog.setText(b[c]);
- mTextDialog.setVisibility(View.VISIBLE);
- }
-
- choose=c;
- invalidate();
- }
- }
-
- break;
- }
- returntrue;
- }
-
-
-
-
-
-
- publicvoidsetOnTouchingLetterChangedListener(
- OnTouchingLetterChangedListeneronTouchingLetterChangedListener){
- this.onTouchingLetterChangedListener=onTouchingLetterChangedListener;
- }
-
-
-
-
-
-
-
- publicinterfaceOnTouchingLetterChangedListener{
- publicvoidonTouchingLetterChanged(Strings);
- }
-
- }
3.CharacterParser这个类是将汉字转换成拼音的类,该拼音没有声调的,该类是单例类,其中定义了三个方法,在这个demo中用到的是getSelling(String chs)方法,将词组转换成拼音
- packagecom.example.sortlistview;
-
-
-
-
-
- publicclassCharacterParser{
- privatestaticint[]pyvalue=newint[]{-20319,-20317,-20304,-20295,-20292,-20283,-20265,-20257,-20242,-20230,-20051,-20036,-20032,
- -20026,-20002,-19990,-19986,-19982,-19976,-19805,-19784,-19775,-19774,-19763,-19756,-19751,-19746,-19741,-19739,-19728,
- -19725,-19715,-19540,-19531,-19525,-19515,-19500,-19484,-19479,-19467,-19289,-19288,-19281,-19275,-19270,-19263,-19261,
- -19249,-19243,-19242,-19238,-19235,-19227,-19224,-19218,-19212,-19038,-19023,-19018,-19006,-19003,-18996,-18977,-18961,
- -18952,-18783,-18774,-18773,-18763,-18756,-18741,-18735,-18731,-18722,-18710,-18697,-18696,-18526,-18518,-18501,-18490,
- -18478,-18463,-18448,-18447,-18446,-18239,-18237,-18231,-18220,-18211,-18201,-18184,-18183,-18181,-18012,-17997,-17988,
- -17970,-17964,-17961,-17950,-17947,-17931,-17928,-17922,-17759,-17752,-17733,-17730,-17721,-17703,-17701,-17697,-17692,
- -17683,-17676,-17496,-17487,-17482,-17468,-17454,-17433,-17427,-17417,-17202,-17185,-16983,-16970,-16942,-16915,-16733,
- -16708,-16706,-16689,-16664,-16657,-16647,-16474,-16470,-16465,-16459,-16452,-16448,-16433,-16429,-16427,-16423,-16419,
- -16412,-16407,-16403,-16401,-16393,-16220,-16216,-16212,-16205,-16202,-16187,-16180,-16171,-16169,-16158,-16155,-15959,
- -15958,-15944,-15933,-15920,-15915,-15903,-15889,-15878,-15707,-15701,-15681,-15667,-15661,-15659,-15652,-15640,-15631,
- -15625,-15454,-15448,-15436,-15435,-15419,-15416,-15408,-15394,-15385,-15377,-15375,-15369,-15363,-15362,-15183,-15180,
- -15165,-15158,-15153,-15150,-15149,-15144,-15143,-15141,-15140,-15139,-15128,-15121,-15119,-15117,-15110,-15109,-14941,
- -14937,-14933,-14930,-14929,-14928,-14926,-14922,-14921,-14914,-14908,-14902,-14894,-14889,-14882,-14873,-14871,-14857,
- -14678,-14674,-14670,-14668,-14663,-14654,-14645,-14630,-14594,-14429,-14407,-14399,-14384,-14379,-14368,-14355,-14353,
- -14345,-14170,-14159,-14151,-14149,-14145,-14140,-14137,-14135,-14125,-14123,-14122,-14112,-14109,-14099,-14097,-14094,
- -14092,-14090,-14087,-14083,-13917,-13914,-13910,-13907,-13906,-13905,-13896,-13894,-13878,-13870,-13859,-13847,-13831,
- -13658,-13611,-13601,-13406,-13404,-13400,-13398,-13395,-13391,-13387,-13383,-13367,-13359,-13356,-13343,-13340,-13329,
- -13326,-13318,-13147,-13138,-13120,-13107,-13096,-13095,-13091,-13076,-13068,-13063,-13060,-12888,-12875,-12871,-12860,
- -12858,-12852,-12849,-12838,-12831,-12829,-12812,-12802,-12607,-12597,-12594,-12585,-12556,-12359,-12346,-12320,-12300,
- -12120,-12099,-12089,-12074,-12067,-12058,-12039,-11867,-11861,-11847,-11831,-11798,-11781,-11604,-11589,-11536,-11358,
- -11340,-11339,-11324,-11303,-11097,-11077,-11067,-11055,-11052,-11045,-11041,-11038,-11024,-11020,-11019,-11018,-11014,
- -10838,-10832,-10815,-10800,-10790,-10780,-10764,-10587,-10544,-10533,-10519,-10331,-10329,-10328,-10322,-10315,-10309,
- -10307,-10296,-10281,-10274,-10270,-10262,-10260,-10256,-10254};
- publicstaticString[]pystr=newString[]{"a","ai","an","ang","ao","ba","bai","ban","bang","bao","bei","ben","beng","bi","bian",
- "biao","bie","bin","bing","bo","bu","ca","cai","can","cang","cao","ce","ceng","cha","chai","chan","chang","chao","che",
- "chen","cheng","chi","chong","chou","chu","chuai","chuan","chuang","chui","chun","chuo","ci","cong","cou","cu","cuan",
- "cui","cun","cuo","da","dai","dan","dang","dao","de","deng","di","dian","diao","die","ding","diu","dong","dou","du",
- "duan","dui","dun","duo","e","en","er","fa","fan","fang","fei","fen","feng","fo","fou","fu","ga","gai","gan","gang",
- "gao","ge","gei","gen","geng","gong","gou","gu","gua","guai","guan","guang","gui","gun","guo","ha","hai","han","hang",
- "hao","he","hei","hen","heng","hong","hou","hu","hua","huai","huan","huang","hui","hun","huo","ji","jia","jian",
- "jiang","jiao","jie","jin","jing","jiong","jiu","ju","juan","jue","jun","ka","kai","kan","kang","kao","ke","ken",
- "keng","kong","kou","ku","kua","kuai","kuan","kuang","kui","kun","kuo","la","lai","lan","lang","lao","le","lei","leng",
- "li","lia","lian","liang","liao","lie","lin","ling","liu","long","lou","lu","lv","luan","lue","lun","luo","ma","mai",
- "man","mang","mao","me","mei","men","meng","mi","mian","miao","mie","min","ming","miu","mo","mou","mu","na","nai",
- "nan","nang","nao","ne","nei","nen","neng","ni","nian","niang","niao","nie","nin","ning","niu","nong","nu","nv","nuan",
- "nue","nuo","o","ou","pa","pai","pan","pang","pao","pei","pen","peng","pi","pian","piao","pie","pin","ping","po","pu",
- "qi","qia","qian","qiang","qiao","qie","qin","qing","qiong","qiu","qu","quan","que","qun","ran","rang","rao","re",
- "ren","reng","ri","rong","rou","ru","ruan","rui","run","ruo","sa","sai","san","sang","sao","se","sen","seng","sha",
- "shai","shan","shang","shao","she","shen","sheng","shi","shou","shu","shua","shuai","shuan","shuang","shui","shun",
- "shuo","si","song","sou","su","suan","sui","sun","suo","ta","tai","tan","tang","tao","te","teng","ti","tian","tiao",
- "tie","ting","tong","tou","tu","tuan","tui","tun","tuo","wa","wai","wan","wang","wei","wen","weng","wo","wu","xi",
- "xia","xian","xiang","xiao","xie","xin","xing","xiong","xiu","xu","xuan","xue","xun","ya","yan","yang","yao","ye","yi",
- "yin","ying","yo","yong","you","yu","yuan","yue","yun","za","zai","zan","zang","zao","ze","zei","zen","zeng","zha",
- "zhai","zhan","zhang","zhao","zhe","zhen","zheng","zhi","zhong","zhou","zhu","zhua","zhuai","zhuan","zhuang","zhui",
- "zhun","zhuo","zi","zong","zou","zu","zuan","zui","zun","zuo"};
- privateStringBuilderbuffer;
- privateStringresource;
- privatestaticCharacterParsercharacterParser=newCharacterParser();
-
- publicstaticCharacterParsergetInstance(){
- returncharacterParser;
- }
-
- publicStringgetResource(){
- returnresource;
- }
-
- publicvoidsetResource(Stringresource){
- this.resource=resource;
- }
-
-
- privateintgetChsAscii(Stringchs){
- intasc=0;
- try{
- byte[]bytes=chs.getBytes("gb2312");
- if(bytes==null||bytes.length>2||bytes.length<=0){
- thrownewRuntimeException("illegalresourcestring");
- }
- if(bytes.length==1){
- asc=bytes[0];
- }
- if(bytes.length==2){
- inthightByte=256+bytes[0];
- intlowByte=256+bytes[1];
- asc=(256*hightByte+lowByte)-256*256;
- }
- }catch(Exceptione){
- System.out.println("ERROR:ChineseSpelling.class-getChsAscii(Stringchs)"+e);
- }
- returnasc;
- }
-
-
- publicStringconvert(Stringstr){
- Stringresult=null;
- intascii=getChsAscii(str);
- if(ascii>0&&ascii<160){
- result=String.valueOf((char)ascii);
- }else{
- for(inti=(pyvalue.length-1);i>=0;i--){
- if(pyvalue[i]<=ascii){
- result=pystr[i];
- break;
- }
- }
- }
- returnresult;
- }
-
-
- publicStringgetSelling(Stringchs){
- Stringkey,value;
- buffer=newStringBuilder();
- for(inti=0;i<chs.length();i++){
- key=chs.substring(i,i+1);
- if(key.getBytes().length>=2){
- value=(String)convert(key);
- if(value==null){
- value="unknown";
- }
- }else{
- value=key;
- }
- buffer.append(value);
- }
- returnbuffer.toString();
- }
-
- publicStringgetSpelling(){
- returnthis.getSelling(this.getResource());
- }
-
- }
4.ClearEditText类是自定义的一个在右侧有删除图片的EditText,当然你也可以用Android原生的EditText,该类我之前有介绍,我这里就不贴上代码了Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框
5.SortAdapter 数据的适配器类,该类需要实现SectionIndexer接口,该接口是用来控制ListView分组的,该接口有三个方法getSectionForPosition(int position),getPositionForSection(int section),getSections(),我们只需要自行实现前面两个方法
- getSectionForPosition(int position)是根据ListView的position来获取该位置上面的name的首字母char的ascii值,例如: 如果该position上面的name是阿妹,首字母就是A,那么此方法返回的就是'A'字母的ascii值,也就是65, 'B'是66,依次类推
- getPositionForSection(int section)就是根据首字母的ascii值来获取在该ListView中第一次出现该首字母的位置,例如:从上面的效果图1中,如果section是65 ,也就是‘B’的ascii值,那么该方法返回的position就是2
然后就是getView()方法,首先我们根据ListView的position调用getSectionForPosition(int position)来获取该位置上面name的首字母的ascii值,然后根据这个ascii值调用getPositionForSection(int section)来获取第一次出现该首字母的position,如果ListView的position 等于根据这个ascii值调用getPositionForSection(int section)来获取第一次出现该首字母的position,则显示分类字母 否则隐藏
6.MainActivity这里面的代码比较简单,我们对ClearEditText设置addTextChangedListener监听,当输入框内容发生变化根据里面的值过滤ListView,里面的值为空显示原来的列表,里面对列表数据进行排序用到PinyinComparator接口,该接口主要是用来比较对象的
- packagecom.example.sortlistview;
-
- importjava.util.ArrayList;
- importjava.util.Collections;
- importjava.util.List;
-
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.text.Editable;
- importandroid.text.TextUtils;
- importandroid.text.TextWatcher;
- importandroid.view.View;
- importandroid.widget.AdapterView;
- importandroid.widget.AdapterView.OnItemClickListener;
- importandroid.widget.ListView;
- importandroid.widget.TextView;
- importandroid.widget.Toast;
-
- importcom.example.sortlistview.SideBar.OnTouchingLetterChangedListener;
-
- publicclassMainActivityextendsActivity{
- privateListViewsortListView;
- privateSideBarsideBar;
-
-
-
- privateTextViewdialog;
- privateSortAdapteradapter;
- privateClearEditTextmClearEditText;
-
-
-
-
- privateCharacterParsercharacterParser;
- privateList<SortModel>SourceDateList;
-
-
-
-
- privatePinyinComparatorpinyinComparator;
-
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initViews();
- }
-
- privatevoidinitViews(){
-
- characterParser=CharacterParser.getInstance();
-
- pinyinComparator=newPinyinComparator();
-
- sideBar=(SideBar)findViewById(R.id.sidrbar);
- dialog=(TextView)findViewById(R.id.dialog);
- sideBar.setTextView(dialog);
-
-
- sideBar.setOnTouchingLetterChangedListener(newOnTouchingLetterChangedListener(){
-
- @Override
- publicvoidonTouchingLetterChanged(Strings){
-
- intposition=adapter.getPositionForSection(s.charAt(0));
- if(position!=-1){
- sortListView.setSelection(position);
- }
-
- }
- });
-
- sortListView=(ListView)findViewById(R.id.country_lvcountry);
- sortListView.setOnItemClickListener(newOnItemClickListener(){
-
- @Override
- publicvoidonItemClick(AdapterView<?>parent,Viewview,
- intposition,longid){
-
- Toast.makeText(getApplication(),((SortModel)adapter.getItem(position)).getName(),Toast.LENGTH_SHORT).show();
- }
- });
-
- SourceDateList=filledData(getResources().getStringArray(R.array.date));
-
-
- Collections.sort(SourceDateList,pinyinComparator);
- adapter=newSortAdapter(this,SourceDateList);
- sortListView.setAdapter(adapter);
-
-
- mClearEditText=(ClearEditText)findViewById(R.id.filter_edit);
-
-
- mClearEditText.addTextChangedListener(newTextWatcher(){
-
- @Override
- publicvoidonTextChanged(CharSequences,intstart,intbefore,intcount){
-
- filterData(s.toString());
- }
-
- @Override
- publicvoidbeforeTextChanged(CharSequences,intstart,intcount,
- intafter){
-
- }
-
- @Override
- publicvoidafterTextChanged(Editables){
- }
- });
- }
-
-
-
-
-
-
-
- privateList<SortModel>filledData(String[]date){
- List<SortModel>mSortList=newArrayList<SortModel>();
-
- for(inti=0;i<date.length;i++){
- SortModelsortModel=newSortModel();
- sortModel.setName(date[i]);
-
- Stringpinyin=characterParser.getSelling(date[i]);
- StringsortString=pinyin.substring(0,1).toUpperCase();
-
-
- if(sortString.matches("[A-Z]")){
- sortModel.setSortLetters(sortString.toUpperCase());
- }else{
- sortModel.setSortLetters("#");
- }
-
- mSortList.add(sortModel);
- }
- returnmSortList;
-
- }
-
-
-
-
-
- privatevoidfilterData(StringfilterStr){
- List<SortModel>filterDateList=newArrayList<SortModel>();
-
- if(TextUtils.isEmpty(filterStr)){
- filterDateList=SourceDateList;
- }else{
- filterDateList.clear();
- for(SortModelsortModel:SourceDateList){
- Stringname=sortModel.getName();
- if(name.toUpperCase().indexOf(
- filterStr.toString().toUpperCase())!=-1
- ||characterParser.getSelling(name).toUpperCase()
- .startsWith(filterStr.toString().toUpperCase())){
- filterDateList.add(sortModel);
- }
- }
- }
-
-
- Collections.sort(filterDateList,pinyinComparator);
- adapter.updateListView(filterDateList);
- }
-
- }
7.PinyinComparator接口用来对ListView中的数据根据A-Z进行排序,前面两个if判断主要是将不是以汉字开头的数据放在后面
- packagecom.example.sortlistview;
-
- importjava.util.Comparator;
-
-
-
-
-
-
- publicclassPinyinComparatorimplementsComparator<SortModel>{
-
- publicintcompare(SortModelo1,SortModelo2){
-
- if(o2.getSortLetters().equals("#")){
- return-1;
- }elseif(o1.getSortLetters().equals("#")){
- return1;
- }else{
- returno1.getSortLetters().compareTo(o2.getSortLetters());
- }
- }
- }
这样我们以后使用A-Z排序就没要局限性了,想加这个效果随时都行,其他的布局和图片之类的文件就不贴出来了,如果大家有兴趣的自行去下载代码吧,如果大家有什么疑问,请在下面留言,我会为大家解答的!