300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字)

AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字)

时间:2019-09-06 12:26:05

相关推荐

AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字)

AutoCompleteTextView具有输入提示的功能,但是它的这种提示不适合对股票列表的过滤,如果你玩过股票软件,就会知道只要输入股票名称的首字母或股票代码就会出现符合匹配的股票,这种过滤怎么实现呢?

还有个问题,汉字具有多音字,如何实现多音字的匹配,比如“长江证券”,无论你输入“cjzq”或者“zjzq”都会匹配到它,这都是需要解决的问题!

匹配的关键在于重写BaseAdapter,让它实现Filterable接口,重写其中的getFilter(),如果你参照ArrayAdaper源码的话,写起来就会容易很多,事实上我就是这么做的,^o^

下面看一下源码:

Java代码packagecom.ql.util; importjava.util.*; importandroid.content.Context; importandroid.util.Log; importandroid.view.*; importandroid.widget.BaseAdapter; importandroid.widget.Filter; importandroid.widget.Filterable; importandroid.widget.TextView; publicclassSearchAdapter<T>extendsBaseAdapterimplementsFilterable{ privateList<T>mObjects; privateList<Set<String>>pinyinList;//支持多音字,类似:{{z,c},{j},{z},{q,x}}的集合 privatefinalObjectmLock=newObject(); privateintmResource; privateintmFieldId=0; privateContextmContext; privateArrayList<T>mOriginalValues; privateArrayFiltermFilter; privateLayoutInflatermInflater; publicstaticfinalintALL=-1;//全部 privateintmaxMatch=10;//最多显示多少个可能选项 //支持多音字 publicSearchAdapter(Contextcontext,inttextViewResourceId,T[]objects,intmaxMatch){ //TODOAuto-generatedconstructorstub init(context,textViewResourceId,0,Arrays.asList(objects)); this.pinyinList=getHanziSpellList(objects); this.maxMatch=maxMatch; } publicSearchAdapter(Contextcontext,inttextViewResourceId,List<T>objects,intmaxMatch){ //TODOAuto-generatedconstructorstub init(context,textViewResourceId,0,objects); this.pinyinList=getHanziSpellList(objects); this.maxMatch=maxMatch; } privatevoidinit(Contextcontext,intresource,inttextViewResourceId,List<T>objects){ mContext=context; mInflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mResource=resource; mObjects=objects; mFieldId=textViewResourceId; } /** *获得汉字拼音首字母列表 */ privateList<Set<String>>getHanziSpellList(T[]hanzi){ List<Set<String>>listSet=newArrayList<Set<String>>(); PinYin4jpinyin=newPinYin4j(); for(inti=0;i<hanzi.length;i++){ listSet.add(pinyin.getPinyin(hanzi[i].toString())); } returnlistSet; } /** *获得汉字拼音首字母列表 */ privateList<Set<String>>getHanziSpellList(List<T>hanzi){ List<Set<String>>listSet=newArrayList<Set<String>>(); PinYin4jpinyin=newPinYin4j(); for(inti=0;i<hanzi.size();i++){ listSet.add(pinyin.getPinyin(hanzi.get(i).toString())); } returnlistSet; } publicintgetCount(){ returnmObjects.size(); } publicTgetItem(intposition){ returnmObjects.get(position); } publicintgetPosition(Titem){ returnmObjects.indexOf(item); } publiclonggetItemId(intposition){ returnposition; } publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ returncreateViewFromResource(position,convertView,parent,mResource); } privateViewcreateViewFromResource(intposition,ViewconvertView, ViewGroupparent,intresource){ Viewview; TextViewtext; if(convertView==null){ view=mInflater.inflate(resource,parent,false); }else{ view=convertView; } try{ if(mFieldId==0){ text=(TextView)view; }else{ text=(TextView)view.findViewById(mFieldId); } }catch(ClassCastExceptione){ Log.e("ArrayAdapter", "YoumustsupplyaresourceIDforaTextView"); thrownewIllegalStateException( "ArrayAdapterrequirestheresourceIDtobeaTextView",e); } text.setText(getItem(position).toString()); returnview; } publicFiltergetFilter(){ if(mFilter==null){ mFilter=newArrayFilter(); } returnmFilter; } privateclassArrayFilterextendsFilter{ @Override protectedFilterResultsperformFiltering(CharSequenceprefix){ FilterResultsresults=newFilterResults(); if(mOriginalValues==null){ synchronized(mLock){ mOriginalValues=newArrayList<T>(mObjects);// } } if(prefix==null||prefix.length()==0){ synchronized(mLock){ //ArrayList<T>list=newArrayList<T>();//无 ArrayList<T>list=newArrayList<T>(mOriginalValues);//List<T> results.values=list; results.count=list.size(); } }else{ StringprefixString=prefix.toString().toLowerCase(); finalArrayList<T>hanzi=mOriginalValues;//汉字String finalintcount=hanzi.size(); finalSet<T>newValues=newHashSet<T>(count);//支持多音字,不重复 for(inti=0;i<count;i++){ finalTvalue=hanzi.get(i);//汉字String finalStringvalueText=value.toString().toLowerCase();//汉字String finalSet<String>pinyinSet=pinyinList.get(i);//支持多音字,类似:{z,c} Iteratoriterator=pinyinSet.iterator();//支持多音字 while(iterator.hasNext()){//支持多音字 finalStringpinyin=iterator.next().toString().toLowerCase();//取出多音字里的一个字母 if(pinyin.indexOf(prefixString)!=-1){//任意匹配 newValues.add(value); } elseif(valueText.indexOf(prefixString)!=-1){//如果是汉字则直接添加 newValues.add(value); } } if(maxMatch>0){//有数量限制 if(newValues.size()>maxMatch-1){//不要太多 break; } } } List<T>list=Set2List(newValues);//转成List results.values=list; results.count=list.size(); } returnresults; } protectedvoidpublishResults(CharSequenceconstraint,FilterResultsresults){ mObjects=(List<T>)results.values; if(results.count>0){ notifyDataSetChanged(); }else{ notifyDataSetInvalidated(); } } } //ListSet相互转换 public<TextendsObject>Set<T>List2Set(List<T>tList){ Set<T>tSet=newHashSet<T>(tList); //TODO具体实现看需求转换成不同的Set的子类。 returntSet; } public<TextendsObject>List<T>Set2List(Set<T>oSet){ List<T>tList=newArrayList<T>(oSet); //TODO需要在用到的时候另外写构造,根据需要生成List的对应子类。 returntList; } }

在源码当中使用了PinYin4j去获得汉字的首字母,由于可能是多音字,所以将每个汉字的拼音都放在了Set中。当然PinYin4j很多强大的功能在这里都用不到,所以被我统统去掉了,这样大大提高了匹配效率。再看一下PinYin4j.java:

Java代码packagecom.ql.util; importjava.util.Arrays; importjava.util.HashSet; importjava.util.Set; publicclassPinYin4j{ publicPinYin4j(){ } /** *字符串集合转换字符串(逗号分隔) * *@authorwyh *@paramstringSet *@return */ publicStringmakeStringByStringSet(Set<String>stringSet){ StringBuilderstr=newStringBuilder(); inti=0; for(Strings:stringSet){ if(i==stringSet.size()-1){ str.append(s); }else{ str.append(s+","); } i++; } returnstr.toString().toLowerCase(); } /** *获取拼音集合 * *@authorwyh *@paramsrc *@returnSet<String> */ publicSet<String>getPinyin(Stringsrc){ char[]srcChar; srcChar=src.toCharArray(); //1:多少个汉字 //2:每个汉字多少种读音 String[][]temp=newString[src.length()][]; for(inti=0;i<srcChar.length;i++){ charc=srcChar[i]; //是中文或者a-z或者A-Z转换拼音(我的需求,是保留中文或者a-z或者A-Z) if(String.valueOf(c).matches("[\\u4E00-\\u9FA5]+")){ String[]t=PinyinHelper.getUnformattedHanyuPinyinStringArray(c); temp[i]=newString[t.length]; for(intj=0;j<t.length;j++){ temp[i][j]=t[j].substring(0,1);//获取首字母 } }elseif(((int)c>=65&&(int)c<=90) ||((int)c>=97&&(int)c<=122)||c>=48&&c<=57||c==42){//a-zA-Z0-9* temp[i]=newString[]{String.valueOf(srcChar[i])}; }else{ temp[i]=newString[]{"null!"}; } } String[]pingyinArray=paiLie(temp); returnarray2Set(pingyinArray);//为了去掉重复项 } /* *求2维数组所有排列组合情况 *比如:{{1,2},{3},{4},{5,6}}共有2中排列,为:1345,1346,2345,2346 */ privateString[]paiLie(String[][]str){ intmax=1; for(inti=0;i<str.length;i++){ max*=str[i].length; } String[]result=newString[max]; for(inti=0;i<max;i++){ Strings=""; inttemp=1;//注意这个temp的用法。 for(intj=0;j<str.length;j++){ temp*=str[j].length; s+=str[j][i/(max/temp)%str[j].length]; } result[i]=s; } returnresult; } publicstatic<TextendsObject>Set<T>array2Set(T[]tArray){ Set<T>tSet=newHashSet<T>(Arrays.asList(tArray)); //TODO没有一步到位的方法,根据具体的作用,选择合适的Set的子类来转换。 returntSet; } /** *@paramargs */ publicstaticvoidmain(String[]args){ //nongyeyinheng,nongyeyinhang,nongyeyinxing PinYin4jt=newPinYin4j(); Stringstr="农业银行1234567890abcdefghijklmnopqrstuvwxyz*"; System.out.println(t.makeStringByStringSet(t.getPinyin(str))); } }

这只是一个工具类,它使用到了PinyinHelper,PinyinHelper是加载字库文件用的,字库文件为/assets/unicode_to_hanyu_pinyin.txt,里面每一个汉字都对应着几个读音。

Java代码packagecom.ql.util; importjava.io.BufferedInputStream; importjava.io.FileNotFoundException; importjava.io.IOException; importjava.util.Properties; publicclassPinyinHelper{ privatestaticPinyinHelperinstance; privatePropertiesproperties=null; publicstaticString[]getUnformattedHanyuPinyinStringArray(charch){ returngetInstance().getHanyuPinyinStringArray(ch); } privatePinyinHelper(){ initResource(); } publicstaticPinyinHelpergetInstance(){ if(instance==null){ instance=newPinyinHelper(); } returninstance; } privatevoidinitResource(){ try{ finalStringresourceName="/assets/unicode_to_hanyu_pinyin.txt"; //finalStringresourceName="/assets/unicode_py.ini"; properties=newProperties(); properties.load(getResourceInputStream(resourceName)); }catch(FileNotFoundExceptionex){ ex.printStackTrace(); }catch(IOExceptionex){ ex.printStackTrace(); } } privateBufferedInputStreamgetResourceInputStream(StringresourceName){ returnnewBufferedInputStream(PinyinHelper.class.getResourceAsStream(resourceName)); } privateString[]getHanyuPinyinStringArray(charch){ StringpinyinRecord=getHanyuPinyinRecordFromChar(ch); if(null!=pinyinRecord){ intindexOfLeftBracket=pinyinRecord.indexOf(Field.LEFT_BRACKET); intindexOfRightBracket=pinyinRecord.lastIndexOf(Field.RIGHT_BRACKET); StringstripedString=pinyinRecord.substring(indexOfLeftBracket +Field.LEFT_BRACKET.length(),indexOfRightBracket); returnstripedString.split(MA); }else returnnull; } privateStringgetHanyuPinyinRecordFromChar(charch){ intcodePointOfChar=ch; StringcodepointHexStr=Integer.toHexString(codePointOfChar).toUpperCase(); StringfoundRecord=properties.getProperty(codepointHexStr); returnfoundRecord; } classField{ staticfinalStringLEFT_BRACKET="("; staticfinalStringRIGHT_BRACKET=")"; staticfinalStringCOMMA=","; } }

至于解析字库,比如有一个汉字是这样的格式:4E01 (ding1,zheng1),保存 到String[]当中就是{"ding1","zheng1"}这样的。但是这样的话到了PinYin4j中还需要使用substring(0,1)截取首字母,效率有些低了,事实上文件中完全可以采用这样的格式存储:E01 (d,z),直接存汉字的首字母就行了,这个另论!

最后,看看使用方法:

Java代码publicclassQuickSearchActivityextendsActivity{ privatestaticfinalStringtag="QuickSearchActivity"; privateAutoCompleteTextViewsearch; privateSlidingDrawermDrawer; publicSearchAdapteradapter=null;// //需要读取 publicString[]hanzi=newString[]{ "长江证券100002","长江证券100001","农业银行200001","工商银行300001", "招商银行100001","建设银行100001","中国银行100002","华夏银行500002", "上海银行100010","浦发银行200009" }; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); initViews(); } privatevoidinitViews(){ search=(AutoCompleteTextView)findViewById(R.id.search); search.setOnItemClickListener(newOnItemClickListener(){ @Override publicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intposition, longid){ //TODOAuto-generatedmethodstub Log.d(tag,"onItemClick:"+position); } }); search.setThreshold(1); adapter=newSearchAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,hanzi,SearchAdapter.ALL);//速度优先 search.setAdapter(adapter);// mDrawer=(SlidingDrawer)findViewById(R.id.slidingdrawer); } }

代码下载地址:/detail/woaieillen/4642921

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。