Android實現模擬搜索功能
本文實例為大傢分享瞭Android實現模擬搜索功能的具體代碼,供大傢參考,具體內容如下
先看效果圖,合適瞭再接著往下看:
我們看到的這個頁面,是由兩部分組成,頂部的自定義的搜索框,和listView組成。
首先我們來實現佈局頁面,自定義搜索框,和設置listView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SearchBoxActivity" android:orientation="vertical" > <EditText android:id="@+id/et_search" android:layout_width="match_parent" android:layout_height="40dp" android:hint="搜索名稱" android:background="@drawable/btn_search" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:maxLines="1" android:maxLength="20" android:inputType="text" android:drawableLeft="@drawable/search" /> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
其中EditeText控件中的 android:background=”@drawable/btn_search”
這個btn_search.xml 是在drawable目錄下定義的。
btn_search.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp" /> <stroke android:width="2dp" android:color="@color/blue" /> <solid android:color="@color/white" /> <corners android:radius="20dp" /> </shape>
之後我們就來實現搜索搜索功能。
使用ListView控件就要給這個控件設置適配器,我們就先來創建一個適配器SearchAdapter,裡面的list集合泛型是我自己創建的一個類,類裡面隻有一個String屬性,實現瞭get和set方法,還有構造器。
在適配器中創建瞭一個內部類MyFilter,繼承瞭Filter類,這個Filter類是Google官方提供的,實現數據過濾。之後我們重寫其中的兩個方法performFiltering 和publishResults 自己制定過濾規則。
public class SearchAdapter extends BaseAdapter implements Filterable { private Context context; private ArrayList<Simulation> list = new ArrayList<>(); private MyFilter filter; //創建MyFilter對象 private FilterListener listener = null; //接口對象 public SearchAdapter(Context context, ArrayList<Simulation> list, FilterListener listener) { this.context = context; this.list = list; this.listener = listener; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { try { final ViewHold hold; if (convertView == null) { hold = new ViewHold(); convertView = LayoutInflater.from(context).inflate(R.layout.item_search, null); hold.tv_simulation = convertView.findViewById(R.id.tv_simulation); convertView.setTag(hold); } else { hold = (ViewHold) convertView.getTag(); } Simulation simulation = list.get(position); hold.tv_simulation.setText(simulation.getText()); } catch (Exception e) { e.printStackTrace(); } return convertView; } public Filter getFilter() { if (filter == null) { filter = new MyFilter(list); } return filter; } /** * 創建內部類MyFilter繼承Filter類,並重寫相關方法,實現數據的過濾 */ class MyFilter extends Filter { //創建集合保存原始數據 private ArrayList<Simulation> original = new ArrayList<>(); public MyFilter(ArrayList<Simulation> original) { this.original = original; } //該方法返回搜索過濾後的數據 @Override protected FilterResults performFiltering(CharSequence constraint) { //創建FilterResults對象 FilterResults filterResults = new FilterResults(); /** * 沒有搜索內容的話就還是給filterResults賦值原始數據的值和大小 * 執行瞭搜索的話,根據搜索規則過濾即可,最後把過濾後的數據的值和大小賦值給filterResults */ if (TextUtils.isEmpty(constraint)) { //取出當前的數據源的值和集合元素個數 //此時返回的filterResults就是原始的數據,不進行過濾 filterResults.values = original; filterResults.count = original.size(); } else { ArrayList<Simulation> mList = new ArrayList<>(); //創建集合保護過濾後的數據 for (Simulation s : original) { //這裡的toLowerCase():是將字符串中的字母全部變為小寫,而非字母則不做改變 if (s.getText().trim().toLowerCase().contains(constraint.toString().trim().toLowerCase())) { //規則匹配的話就往集合中添加該數據 mList.add(s); } } filterResults.values = mList; filterResults.count = mList.size(); } return filterResults; } //該方法用來刷新用戶界面,根據過濾後的數據重新展示列表 @Override protected void publishResults(CharSequence constraint, FilterResults results) { //獲取過濾後的數據 list = (ArrayList<Simulation>) results.values; //如果接口對象不為空,那麼調用接口中的方法獲取過濾後的數據,具體的實現在new這個接口的時候重寫的方法裡執行 if (listener != null) { listener.getFilterData(list); } //刷新數據源顯示 //通知數據觀察者當前所關聯的數據源已經發生改變,任何與該數據有關的視圖都應該去刷新自己。 notifyDataSetChanged(); } } public interface FilterListener{ void getFilterData(List<Simulation> list); } public final class ViewHold { private TextView tv_simulation; } }
之後我們在SearchBoxActivity中,對EditText控件的TextChanged進行實時監聽,然後對輸入的關鍵字與ListView中的數據源進行循環遍歷、過濾,再把新數據源通過適配器刷新到ListView上。這麼一個過程。
public class SearchBoxActivity extends AppCompatActivity { private static final String TAG = "SearchBoxActivity"; private EditText et_search; private ListView listView; private SearchAdapter searchAdapter; private ArrayList<Simulation> list = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search_box); et_search = findViewById(R.id.et_search); listView = findViewById(R.id.listView); String data[] = new String[]{"大數據", "Android開發", "Java開發", "web前端開發", "網頁開發", "IOS開發"}; for (int i = 0; i < 6; i++) { Simulation simulation = new Simulation(data[i]); list.add(simulation); } searchAdapter = new SearchAdapter(this, list, new SearchAdapter.FilterListener() { @Override public void getFilterData(List<Simulation> list) { //這裡可以拿到過濾後的數據,所以在這裡可以對搜索後的數據進行操作 Log.e(TAG, "接口回調成功"); Log.e(TAG, list.toString()); setItemClick(list); } }); //設置適配器 listView.setAdapter(searchAdapter); //設置監聽 setListeners(); } private void setListeners() { //沒有進行搜索的時候,也要添加對listView的item單擊監聽 setItemClick(list); /** * 對編輯框添加文本改變監聽,搜索的具體功能是在這裡實現 * 文字改變的時候進行搜索,關鍵方法是重寫onTextChanged()方法 */ et_search.addTextChangedListener(new TextWatcher() { //每次EditText文本改變之前的時候,會回調這個方法 @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { //s 輸入框中改變前的字符串信息 //start 輸入框中改變前的字符串的起始位置 //count 輸入框中改變前後的字符串改變數量一般為0 //after 輸入框中改變後的字符串與起始位置的偏移量 } //每次EditText文本改變的時候,會回調這個方法 @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //第一個參數s 的含義: 輸入框中改變後的字符串信息 //start 輸入框中改變後的字符串的起始位置 //before 輸入框中改變前的字符串的位置 默認為0 //count 輸入框中改變後的一共輸入字符串的數量 if (searchAdapter != null) { searchAdapter.getFilter().filter(s); } } //每次EditText文本改變之後的時候,會回調這個方法 @Override public void afterTextChanged(Editable s) { //edit 輸入結束呈現在輸入框中的信息 } }); } private void setItemClick(List<Simulation> filter_list) { listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(SearchBoxActivity.this, filter_list.get(position).getText(), Toast.LENGTH_SHORT).show(); } }); } }
這樣就實現瞭模擬搜索的功能,並且在代碼中已經給出瞭詳細的註釋。
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- GridView實現桌面圖標顯示案例
- Android BaseAdapter適配器詳解用法
- Android ListView仿微信聊天界面
- Android入門之實現自定義可復用的BaseAdapter
- Android入門教程之ListView的具體使用詳解