如何为AutoCompleteTextView创build自定义BaseAdapter

我一直在为AutoCompleteTextView创build一个自定义的ArrayAdapter时遇到困难,即使在Internet上find下面的代码,也会出现这样的错误:

  • 下拉不会出现。
  • 自定义对象及其细节不会出现。

所以对于那些和我有同样问题的人,我推荐使用BaseAdapter来代替AutoCompleteTextView。

以下是我使用ArrayAdapter的工作代码。

假设来自Web服务的响应数据如下所示:

[ { "id": "1", "name": "Information Technology" }, { "id": "2", "name": "Human Resources" }, { "id": "3", "name": "Marketing and PR" }, { "id": "4", "name": "Research and Developement" } ] 

然后在你的Android客户端中:

部门级别:

 public class Department { public int id; public String name; } 

自定义适配器类:

 public class DepartmentArrayAdapter extends ArrayAdapter<Department> { private final Context mContext; private final List<Department> mDepartments; private final List<Department> mDepartments_All; private final List<Department> mDepartments_Suggestion; private final int mLayoutResourceId; public DepartmentArrayAdapter(Context context, int resource, List<Department> departments) { super(context, resource, departments); this.mContext = context; this.mLayoutResourceId = resource; this.mDepartments = new ArrayList<>(departments); this.mDepartments_All = new ArrayList<>(departments); this.mDepartments_Suggestion = new ArrayList<>(); } public int getCount() { return mDepartments.size(); } public Department getItem(int position) { return mDepartments.get(position); } public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { try { if (convertView == null) { LayoutInflater inflater = ((Activity) mContext).getLayoutInflater(); convertView = inflater.inflate(mLayoutResourceId, parent, false); } Department department = getItem(position); TextView name = (TextView) convertView.findViewById(R.id.textView); name.setText(department.name); } catch (Exception e) { e.printStackTrace(); } return convertView; } @Override public Filter getFilter() { return new Filter() { @Override public String convertResultToString(Object resultValue) { return ((Department) resultValue).name; } @Override protected FilterResults performFiltering(CharSequence constraint) { if (constraint != null) { mDepartments_Suggestion.clear(); for (Department department : mDepartments_All) { if (department.name.toLowerCase().startsWith(constraint.toString().toLowerCase())) { mDepartments_Suggestion.add(department); } } FilterResults filterResults = new FilterResults(); filterResults.values = mDepartments_Suggestion; filterResults.count = mDepartments_Suggestion.size(); return filterResults; } else { return new FilterResults(); } } @Override protected void publishResults(CharSequence constraint, FilterResults results) { mDepartments.clear(); if (results != null && results.count > 0) { // avoids unchecked cast warning when using mDepartments.addAll((ArrayList<Department>) results.values); List<?> result = (List<?>) results.values; for (Object object : result) { if (object instanceof Department) { mDepartments.add((Department) object); } } } else if (constraint == null) { // no filter, add entire original list back in mDepartments.addAll(mDepartments_All); } notifyDataSetChanged(); } }; } } 

主要活动:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView); mAutoCompleteTextView.setThreshold(1); new DepartmentRequest().execute(); } private class DepartmentRequest extends AsyncTask<Void, Void, JSONArray> { @Override protected JSONArray doInBackground(Void... voids) { OkHttpJsonArrayRequest request = new OkHttpJsonArrayRequest(); try { return request.get("http://..."); } catch (IOException | JSONException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(JSONArray jsonArray) { super.onPostExecute(jsonArray); if (jsonArray != null && jsonArray.length() > 0) { Gson gson = new Gson(); Department[] departments = gson.fromJson(jsonArray.toString(), Department[].class); mDepartmentList = Arrays.asList(departments); mDepartmentArrayAdapter = new DepartmentArrayAdapter(mContext, R.layout.simple_text_view, mDepartmentList); mAutoCompleteTextView.setAdapter(mDepartmentArrayAdapter); } } } private class OkHttpJsonArrayRequest { OkHttpClient client = new OkHttpClient(); // HTTP GET REQUEST JSONArray get(String url) throws IOException, JSONException { Request request = new Request.Builder() .url(url) .build(); Response response = client.newCall(request).execute(); return new JSONArray(response.body().string()); } } 

这是截图:

BNK的截图

希望这可以帮助!

自定义BaseAdapter类

 public class ObjectAdapter extends BaseAdapter implements Filterable { private Context context; private ArrayList<Object> originalList; private ArrayList<Object> suggestions = new ArrayList<>(); private Filter filter = new CustomFilter(); /** * @param context Context * @param originalList Original list used to compare in constraints. */ public ObjectAdapter(Context context, ArrayList<Object> originalList) { this.context = context; this.originalList = originalList; } @Override public int getCount() { return suggestions.size(); // Return the size of the suggestions list. } @Override public Object getItem(int position) { return suggestions.get(position).getCountryName(); } @Override public long getItemId(int position) { return 0; } /** * This is where you inflate the layout and also where you set what you want to display. * Here we also implement a View Holder in order to recycle the views. */ @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(context); ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.adapter_autotext, parent, false); holder = new ViewHolder(); holder.autoText = (TextView) convertView.findViewById(R.id.autoText); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.autoText.setText(suggestions.get(position).getCountryName()); return convertView; } @Override public Filter getFilter() { return filter; } private static class ViewHolder { TextView autoText; } /** * Our Custom Filter Class. */ private class CustomFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { suggestions.clear(); if (originalList != null && constraint != null) { // Check if the Original List and Constraint aren't null. for (int i = 0; i < originalList.size(); i++) { if (originalList.get(i).getCountryName().toLowerCase().contains(constraint)) { // Compare item in original list if it contains constraints. suggestions.add(originalList.get(i)); // If TRUE add item in Suggestions. } } } FilterResults results = new FilterResults(); // Create new Filter Results and return this to publishResults; results.values = suggestions; results.count = suggestions.size(); return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { if (results.count > 0) { notifyDataSetChanged(); } else { notifyDataSetInvalidated(); } } } } 

主要活动类

 public class MainActivity extends AppCompatActivity{ private SGetCountryListAdapter countryAdapter; private ArrayList<SGetCountryList> countryList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); country = (AutoCompleteTextView) findViewById(R.id.country); countryAdapter = new SGetCountryListAdapter(getApplicationContext(), ConnectionParser.SGetCountryList); country.setAdapter(countryAdapter); country.setThreshold(1); } } 

下拉布局

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/autoText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="16dp" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:textColor="@color/black" /> </LinearLayout> 

我的原始列表中有从Web服务获取的数据,所以我们假设它已经有数据。 当然,您可以通过添加更多的视图来更好地自定义下拉菜单,只是不要忘记更新适配器,以便合并新的视图。