1. 程式人生 > >使用EditText+ListView並結合TextWatcher實現輸入關鍵字篩選資料

使用EditText+ListView並結合TextWatcher實現輸入關鍵字篩選資料

    想必大家應該遇到過這樣的情況,當點選Spinner控制元件後彈出的列表內容超多,一個一個滑動著去尋找所要的項很麻煩,尤其是當自己知道想要選擇的內容,這時候如果我們只需要輸入某些關鍵字,就可以講上百條資料篩選出幾十條甚至更少,豈不是會方便很多。

    其實這是專案中的一個需求,由於目前公司接觸的多數和資料採集相關的PDA專案,有很多填寫項一個spinner已經不方便滿足需求,雖然客戶還沒有提出,但提前做好優化總是沒有錯的,所以專案組的同事提出這個需求並讓我嘗試著去做出來,當中給了我不少幫助和意見。

    閒言少敘,簡單說下這個demo的實現,點選一個button,彈出一個類似spinner的介面,包含一個edittext和listview,當在輸入框中鍵入關鍵字時,下面的listview所顯示的資料可以隨之進行篩選,點選item,將所選值返回給button。實現其實不難,只不過接觸了一個新的知識而已,就是TextWatcher,它本身是一個介面,需要實現並覆蓋它的三個方法,在每個方法中執行相應的操作,然後在需要的控制元件上新增監聽即可。先來看本Demo實現後的效果

                                                                                             

                                               進入後點擊按鈕                                                                                                    彈出資料介面

                                                                                             

                                             輸入關鍵字進行篩選                                                                                               點選子專案返回給按鈕

以下是部分程式碼的實現,其實比較簡單,唯一不太熟悉的就是TextWatcher,因為之前沒用過,但是很簡單,只有三個方法,現實了就OK了

        首先介紹一下這個自己寫的類,它實現了一個數據的值value和顯示名稱Name的繫結,可以很方便的用於新增資料,當然也可以使用自己的方法去新增資料,本例子我就用這個了。

package com.cogent.enumbutton;

/**
 * 一個Value(繫結值)-Name(顯示名稱)物件,如:1-漢族
 */
public class ValueNameDomain {

	private String Value;//繫結的值
	private String Name;//顯示的選項名稱
	
	public ValueNameDomain(){}
	
	public ValueNameDomain(String name,String value){
		this.Name = name;
		this.Value = value;
	}
	
	/**
	 * 獲取繫結的值
	 */
	public String getValue() {
		return Value;
	}
	/**
	 * 設定繫結的值
	 */
	public void setValue(String value) {
		this.Value = value;
	}
	/**
	 * 獲取顯示的選項名稱
	 */
	public String getName() {
		return Name;
	}
	/**
	 * 設定顯示的選項名稱
	 */
	public void setName(String name) {
		this.Name = name;
	}
	@Override
	public String toString() {
		return Name;
	}
	
	
}

這個是demo的關鍵了,運用一個視窗樣式的activity實現類似spinner的功能,具體的地方我都進行了自己能看懂的註解,對輸入控制元件新增addTextChangedListener,並實現其中的三個方法就完成了,三個方法比較簡單,為別

也就是文字發生改變之前,改變時,和改變之後進行相應的操作,看看SDK就神馬都解決了

package com.cogent.enumbutton;

import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

public class EditTextListView extends Activity {
	//按鈕靜態快取,該用法可以避免使用startActivityForResult來獲取按鈕返回的時間
	public static Button btn;
	private EditText edit_search;
	private ListView lv;
	private EditTextListViewAdapter adapter;
	List<ValueNameDomain> list = new ArrayList<ValueNameDomain>();//所有的資料list
	List<ValueNameDomain> newlist = new ArrayList<ValueNameDomain>();//查詢後的資料list

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.edittextlistview);
		init();
		initDefaultLists();

	}

	//初始化控制元件
	private void init() {
		edit_search = (EditText) findViewById(R.id.edit_search);
		//為輸入新增TextWatcher監聽文字的變化
		edit_search.addTextChangedListener(new TextWatcher_Enum());
		adapter = new EditTextListViewAdapter(this, list);
		lv = (ListView) findViewById(R.id.edittextListview);
		lv.setAdapter(adapter);
		lv.setOnItemClickListener(new onclick());
	}

	//新增資料
	private void initDefaultLists() {
		ValueNameDomain domain = new ValueNameDomain();
		for (int i = 1; i <= 20; i++) {
			domain = new ValueNameDomain();
			domain.setName("測試資料" + i);
			domain.setValue(i + "");
			list.add(domain);
		}

	}

	//當editetext變化時呼叫的方法,來判斷所輸入是否包含在所屬資料中
	private List<ValueNameDomain> getNewData(String input_info) {
		//遍歷list
		for (int i = 0; i < list.size(); i++) {
			ValueNameDomain domain = list.get(i);
			//如果遍歷到的名字包含所輸入字串
			if (domain.getName().contains(input_info)) {
				//將遍歷到的元素重新組成一個list
				ValueNameDomain domain2 = new ValueNameDomain();

				domain2.setName(domain.getName());
				domain2.setValue(i + "");
				newlist.add(domain2);
			}
		}
		return newlist;
	}

	//button的點選事件
	class onclick implements OnItemClickListener {

		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
			TextView text = (TextView) view.findViewById(R.id.tvData);
			String str = (String) text.getText();
			btn.setText(str);
			EditTextListView.this.finish();
		}

	}

	//TextWatcher介面
	class TextWatcher_Enum implements TextWatcher {

		//文字變化前
		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {

		}

		//文字變化時
		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			newlist.clear();
			if (edit_search.getText() != null) {
				String input_info = edit_search.getText().toString();
				newlist = getNewData(input_info);
				adapter = new EditTextListViewAdapter(EditTextListView.this,
						newlist);
				lv.setAdapter(adapter);
			}
		}

		//文字變化後
		@Override
		public void afterTextChanged(Editable s) {

		}

	}

}


這是個比較實用的demo,打算進一步整理出來封裝起來,以後專案要是用到的話就可以直接拿來用啦,結尾附上原始碼,希望大家可以一起學習分享,堅持記錄自己的android路程。