最近在做Android开发,使用其控件AutoCompleteTextView时发现只能实现前缀匹配,也就是说只能匹配以所输入的字符开始的数据,觉得google这个做的不好,不够人性化。要是数据非常多,而又确实不记得所要找的数据以什么字符开始的,那该怎么办呢?哈哈,作为中国共产党领导下的共产主义下的和谐社会下的伟大而又苦X的程序猿,这小小的问题怎么能难得住我们。
大家知道,Android系统是开源的,也就是说我们可以通过修改其源码来解决这个问题。
先看截图:
上图中左边是AutoCompeteTextView控件前缀匹配结果,右边的是通过修改其源码实现其中缀和后缀匹配。
接下来说下怎么修改Android源码,当然要想修改其源码,必须要下载Android源码,建议有条件的童鞋们使用Git工具自己下载,因为Android系统一直在更新,其源码也在不断地更改。懒虫们可以从博文结尾的链接中下载。
首先在android\widget的目录下找到ArrayAdapter.java文件并打开,下面是部分源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | private class ArrayFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence prefix) { FilterResults results = new FilterResults(); if (mOriginalValues == null) { synchronized (mLock) { mOriginalValues = new ArrayList<T>(mObjects); } } if (prefix == null || prefix.length() == 0) { synchronized (mLock) { ArrayList<T> list = new ArrayList<T>(mOriginalValues); results.values = list; results.count = list.size(); } } else { String prefixString = prefix.toString().toLowerCase(); final ArrayList<T> values = mOriginalValues; final int count = values.size(); final ArrayList<T> newValues = new ArrayList<T>(count); for (int i = 0; i < count; i++) { final T value = values.get(i); final String valueText = value.toString().toLowerCase(); // First match against the whole, non-splitted value if (valueText.startsWith(prefixString)) { newValues.add(value); } else { final String[] words = valueText.split(" "); final int wordCount = words.length; for (int k = 0; k < wordCount; k++) { if (words[k].startsWith(prefixString)) { newValues.add(value); break; } } } } results.values = newValues; results.count = newValues.size(); } return results; } |
找到”if (words[k].startsWith(prefixString)) {“这行,将其改为“if words[k].indexOf(prefixString)!=-1) {”便可。还需将ArrayAdapter所属的包改为自己的包。如果以后还会用到,建议将其打包为.jar文件。
项目目录结构如下:
下面是Main Activity,写了注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class AutoCompleteTextViewActivity extends Activity { /** Called when the activity is first created. */ private AutoCompleteTextView actv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String[] s=new String[]{"aaaa","abcd","bbac","dbca"}; actv=(AutoCompleteTextView)findViewById(R.id.autoCompleteTextView1); //系统默认为前缀匹配 //android.widget.ArrayAdapter<String> adapter=new android.widget.ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,s); //通过修改android源码实现中缀和后缀匹配 com.zhang.autocomplete.ArrayAdapter<String> adapter=new com.zhang.autocomplete.ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,s); //Specifies the minimum number of characters the user has to type in the edit box before the drop down list is shown. //setThreshold的参数也就是说要实现匹配所应输入的最小字符数,这里为1,指只要输入一个字符便开始匹配,为2则需输入2个字符才开始匹配,以此类推 actv.setThreshold(1); actv.setAdapter(adapter); } } |
只要注意这里的ArrayAdapter使用的是自己修改的,前面加上包名以示区别。
项目源码下载:https://github.com/johnsonz/android-autocompletetextview