Android中修改原始碼實現AutoCompeteTextView控制元件的模糊匹配

jia635發表於2014-08-17

最近在做Android開發,使用其控制元件AutoCompleteTextView時發現只能實現字首匹配,也就是說只能匹配以所輸入的字元開始的資料,覺得google這個做的不好,不夠人性化。要是資料非常多,而又確實不記得所要找的資料以什麼字元開始的,那該怎麼辦呢?哈哈,作為中國共產黨領導下的共產主義下的和諧社會下的偉大而又苦X的程式猿,這小小的問題怎麼能難得住我們。

大家知道,Android系統是開源的,也就是說我們可以通過修改其原始碼來解決這個問題。

先看截圖:

                               

上圖中左邊是AutoCompeteTextView控制元件字首匹配結果,右邊的是通過修改其原始碼實現其中綴和字尾匹配。

接下來說下怎麼修改Android原始碼,當然要想修改其原始碼,必須要下載Android原始碼,建議有條件的童鞋們使用Git工具自己下載,因為Android系統一直在更新,其原始碼也在不斷地更改。懶蟲們可以從博文結尾的連結中下載。

首先在android\widget的目錄下找到ArrayAdapter.java檔案並開啟,下面是部分原始碼:

private class <span style="padding: 0px; margin: 0px; color: rgb(204, 0, 0);">ArrayFilter </span>extends Filter {
        @Override
        protected FilterResults <span style="padding: 0px; margin: 0px; color: rgb(255, 0, 0);">performFiltering(CharSequence prefix)</span> {
            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++) {
                           <span style="padding: 0px; margin: 0px; color: rgb(255, 0, 0);"> if (words[k].startsWith(prefixString)) {</span>
                                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,寫了註釋:

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);
    }
}

相關文章