用AutoCompleteTextView實現歷史記錄提示
阿新 • • 發佈:2019-02-16
這畫面不陌生吧,百度的提示,他的詞庫並不是歷史記錄,是搜尋引擎收集的當前最常搜尋的內容。假如我們也要在android的應用實現如上功能怎麼做呢?
方法很簡單,android已經幫我們寫好了api ,這裡就用到了AutoCompleteTextView元件。
網上有不少教程,那個提示框字符集都是事先寫好的,例如用一個String[] 陣列去包含了這些資料,但是,我們也可以吧使用者輸入的作為歷史記錄儲存
下面先上我寫的程式碼:
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
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 Read_historyActivity extends Activity implements
OnClickListener {
private AutoCompleteTextView autoTv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
autoTv = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
initAutoComplete("history",autoTv);
Button search = (Button) findViewById(R.id.button1);
search.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// 這裡可以設定:當搜尋成功時,才執行儲存操作
saveHistory("history",autoTv);
}
/**
* 初始化AutoCompleteTextView,最多顯示5項提示,使
* AutoCompleteTextView在一開始獲得焦點時自動提示
* @param field 儲存在sharedPreference中的欄位名
* @param auto 要操作的AutoCompleteTextView
*/
private void initAutoComplete(String field,AutoCompleteTextView auto) {
SharedPreferences sp = getSharedPreferences("network_url", 0);
String longhistory = sp.getString("history", "nothing");
String[] hisArrays = longhistory.split(",");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, hisArrays);
//只保留最近的50條的記錄
if(hisArrays.length > 50){
String[] newArrays = new String[50];
System.arraycopy(hisArrays, 0, newArrays, 0, 50);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, newArrays);
}
auto.setAdapter(adapter);
auto.setDropDownHeight(350);
auto.setThreshold(1);
auto.setCompletionHint("最近的5條記錄");
auto.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
AutoCompleteTextView view = (AutoCompleteTextView) v;
if (hasFocus) {
view.showDropDown();
}
}
});
}
/**
* 把指定AutoCompleteTextView中內容儲存到sharedPreference中指定的字元段
* @param field 儲存在sharedPreference中的欄位名
* @param auto 要操作的AutoCompleteTextView
*/
private void saveHistory(String field,AutoCompleteTextView auto) {
String text = auto.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();
}
}
}
上面的程式碼我實現了autocomplettextview的從sharepreference中讀取歷史記錄並顯示的功能,當沒有任何輸入時,提示最新的5項歷史記錄(這裡可以加個條件,當有歷史記錄時才顯示)補上佈局的程式碼
當之有一個edittext或者auto的時候,進入畫面時是預設得到焦點的,要想去除焦點,可以在auto之前加一個o畫素的layout,並設定他先得到焦點。<?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"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <LinearLayout android:layout_width="0px" android:layout_height="0px" android:focusable="true" android:focusableInTouchMode="true"></LinearLayout> <AutoCompleteTextView android:hint="請輸入文字進行搜尋" android:layout_height="wrap_content" android:layout_width="match_parent" android:id="@+id/autoCompleteTextView1"> </AutoCompleteTextView> <Button android:text="搜尋" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout>
效果圖如下
下面出現的是原始碼內容
需要注意的是,我這裡用到的AutoCompleteTextView的幾個方法
1. setAdapter()方法:這裡要傳遞的adapter引數必須是繼承ListAdapter和Filterable的,其中arrayAdapter和simpleAdapter都能滿足要求,我們常用arrayAdapter,因為他不需要像simpleAdapte那樣設定他的顯示位置和textview元件。
要想掌握它,就必須檢視他的原始碼,我們可以看看arrayadapter是如何實現
凡是繼承了Filterable的adapter都必須重寫getFilter介面方法
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
這個filter 就是實現過濾方法的物件,同樣,我們可以檢視他的原始碼是如何實現的 /**
* <p>An array filter constrains the content of the array adapter with
* a prefix. Each item that does not start with the supplied prefix
* is removed from the list.</p>
*/
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;
}
這是arrayAdapter自定義的一個私有內部類,所謂私有,就意味著你不能通過繼承去修改這種過濾方法,同樣你也不能直接得到他過濾後結果集results。假如你想使用新的過濾方法,你必須重寫getfilter()方法,返回的filter物件是你要新建的filter物件(在裡面包含performFiltering()方法重新構造你要的過濾方法)2.setDropDownHeight方法 ,用來設定提示下拉框的高度,注意,這只是限制了提示下拉框的高度,提示資料集的個數並沒有變化
3.setThreshold方法,設定從輸入第幾個字元起出現提示
4.setCompletionHint方法,設定提示框最下面顯示的文字
5.setOnFocusChangeListener方法,裡面包含OnFocusChangeListener監聽器,設定焦點改變事件
6.showdropdown方法,讓下拉框彈出來
我沒有用到的一些方法列舉
1.clearListSelection,去除selector樣式,只是暫時的去除,當用戶再輸入時又重新出現
2.dismissDropDown,關閉下拉提示框
3.enoughToFilter,這是一個是否滿足過濾條件的方法,sdk建議我們可以重寫這個方法
4. getAdapter,得到一個可過濾的列表介面卡
5.getDropDownAnchor,得到下拉框的錨計的view的id
6.getDropDownBackground,得到下拉框的背景色
7.setDropDownBackgroundDrawable,設定下拉框的背景色
8.setDropDownBackgroundResource,設定下拉框的背景資源
9.setDropDownVerticalOffset,設定下拉表垂直偏移量,即是list裡包含的資料項數目
10.getDropDownVerticalOffset ,得到下拉表垂直偏移量
11..setDropDownHorizontalOffset,設定水平偏移量
12.setDropDownAnimationStyle,設定下拉框的彈出動畫
13.getThreshold,得到過濾字元個數
14.setOnItemClickListener,設定下拉框點選事件
15.getListSelection,得到下拉框選中為位置
16.getOnItemClickListener。得到單項點選事件
17.getOnItemSelectedListener得到單項選中事件
18.getAdapter,得到那個設定的介面卡
一些隱藏方法和構造我沒有列舉了,具體可以參考api文件
可下載我的寫的demo: http://download.csdn.net/detail/iamkila/4042528