簡介 在我們平常上網的時候經常會用到Google或百度,在輸入框中輸入我們想要輸入的資訊就會出現其他與其相關的提示資訊,非常方便。這種效果在Android中是用AutoCompleteTextView實現的,AutoCompleteTextView是一個可以編輯的文本view,當使用者鍵入時,會自動顯示完成建議資訊。 建議列表顯示在下拉式清單方塊中,可以選中某項代替編輯框裡的內容。 當使用者點擊斷行符號鍵時,或者什麼也沒有選中點擊ENTER建時下拉式清單會自動消失。 建議列表是從一個資料配接器擷取的資料。 step1:建立一個項目AutoCompletestep2:設計應用的UI介面 /layout/main.xml[html] <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- 當之有一個EditText或者AutoCompleteTextView的時候,進入畫面時是預設得到焦點的。 要想去除焦點,可以在auto之前加一個o像素的layout,並設定他先得到焦點。 --> <LinearLayout android:layout_width="0px" android:layout_height="0px" android:focusable="true" android:focusableInTouchMode="true"></LinearLayout> <!-- 定義一個自動完成文字框,指定輸入一個字元後進行提示 --> <AutoCompleteTextView android:id="@+id/auto" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="請輸入文字進行搜尋" android:completionHint="最近的5條記錄" android:dropDownHorizontalOffset="20dp" android:completionThreshold="1" android:dropDownHeight="fill_parent"/> <!-- android:completionHint 設定出現在下拉式功能表中的提示標題 android:completionThreshold 設定使用者至少輸入多少個字元才會顯示提示 android:dropDownHorizontalOffset 設定下拉式功能表於文字框之間的水平位移。下拉式功能表預設與文字框靠左對齊 android:dropDownVerticalOffset 設定下拉式功能表於文字框之間的垂直位移。下拉式功能表預設緊跟文字框 android:dropDownHeight 設定下拉式功能表的高度 android:dropDownWidth 設定下拉式功能表的寬度 --> <Button android:text="搜尋" android:id="@+id/search" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> step3:MainActivity.java[java] package cn.roco.autocomplete; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; public class MainActivity extends Activity { private AutoCompleteTextView autoCompleteTextView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); autoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.auto); initAutoComplete("history", autoCompleteTextView); Button searchButton = (Button) findViewById(R.id.search); searchButton.setOnClickListener(new MyOnClickListener()); } private final class MyOnClickListener implements OnClickListener { @Override public void onClick(View v) { saveHistory("history", autoCompleteTextView); } } /** * 把指定AutoCompleteTextView中內容儲存到sharedPreference中指定的字元段 * * @param field * 儲存在sharedPreference中的欄位名 * @param autoCompleteTextView * 要操作的AutoCompleteTextView */ private void saveHistory(String field, AutoCompleteTextView autoCompleteTextView) { String text = autoCompleteTextView.getText().toString(); SharedPreferences sp = getSharedPreferences("network_url", 0); String longhistory = sp.getString(field, "nothing"); if (!longhistory.contains(text + ",")) { StringBuilder sb = new StringBuilder(longhistory); sb.insert(0, text + ","); sp.edit().putString("history", sb.toString()).commit(); } } /** * 初始化AutoCompleteTextView,最多顯示5項提示,使 AutoCompleteTextView在一開始獲得焦點時自動提示 * * @param field * 儲存在sharedPreference中的欄位名 * @param autoCompleteTextView * 要操作的AutoCompleteTextView */ private void initAutoComplete(String field, AutoCompleteTextView autoCompleteTextView) { SharedPreferences sp = getSharedPreferences("network_url", 0); String longhistory = sp.getString("history", "nothing"); String[] histories = longhistory.split(","); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, histories); // 只保留最近的50條的記錄 if (histories.length > 50) { String[] newHistories = new String[50]; System.arraycopy(histories, 0, newHistories, 0, 50); adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, newHistories); } autoCompleteTextView.setAdapter(adapter); autoCompleteTextView .setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { AutoCompleteTextView view = (AutoCompleteTextView) v; if (hasFocus) { view.showDropDown(); } } }); } } step4:部署應用到模擬器中step5:進行幾次輸入,並點擊搜尋按鈕儲存記錄後,退出應用再重新進入應用step6:這個時候再進行搜尋就會有自動補全的效果: 附註: 熟悉android列表開發的話,對於Adapter應該非常熟悉,上面的執行個體代碼,使用了android提供的ArrayAdapter,給予AutoCompleteTextView 綁定資料與視圖,我們要定製,首先從這裡開始。 和其他Adaper一樣,ArrayAdapter的基類也是BaseAdapter,我們可以定製自己的Adapter了。 可是一運行,木有反應,沒有一點提示? 的確,我們的視圖與資料是綁定了,可是AutoCompleteTextView 卻不能根據我們的Adapter擷取到合適的資料,因為adapter不符合要求! 我們反過來再研究一下ArrayAdapter,它除了是BaseAdapter的子類,它還實現了 Filterable 介面! 我們在AutoAdapter中,實現該介面,並返回一個自訂的 Filter 那個AutoMailFilter又是一個什麼樣子的類呢? 先細細想想 AutoCompleteTextView 是怎樣工作的,對,它只是對我們所輸入的一些字元,進行過濾、索引,並組成相應的視圖反饋給我們的使用者,以提高我們的輸入效率! 那接下來就是構建核心過濾器的時候了,AutoCompleteTextView 只會接收過濾後的資料,所以我們的資料來源會多出一份拷貝,一份是原始的,一份則是過濾後的: 在AutoMailFilter裡面,由於繼承了,我們必須實現兩個重要的方法: protected FilterResults performFiltering(CharSequence prefix) 在這個方法裡面定製過濾策略,根據輸入的prefix對資料進行過濾,並組裝成FilterResults 結果返回; protected void publishResults(CharSequence constraint, FilterResults results) 這個方法則是發布結果用的,把上面方法的結果按照一定的要求進行處理後,通知Adapter進行資料檢視的重新整理 總結: 按照 AutoCompleteTextView 的工作流程,它依賴兩個組件,Adapter 和 Filter,一個是視圖的處理,一個是資料過濾處理,對這兩個組件進行深度定製,我們就可以隨心所欲了。