Search code examples
androidandroid-arrayadapterbaseadapterautocompletetextview

How to create custom BaseAdapter for AutoCompleteTextView


I've been having difficulty creating a custom ArrayAdapter for AutoCompleteTextView such errors that would come up despite following code found on the internet would be:

  • Dropdown would not appear.
  • Custom Objects and their details would not appear.

So for those who are having or had the same problem as me, I recommend using BaseAdapter for AutoCompleteTextView instead.


Solution

  • The following is my working code using ArrayAdapter.

    Let's assume the reponse data from web service looks like the following:

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

    Then in your Android client:

    Department class:

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

    Custom Adapter class:

    public class DepartmentArrayAdapter extends ArrayAdapter<Department> {
        private final Context mContext;
        private final List<Department> mDepartments;
        private final List<Department> mDepartmentsAll;
        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.mDepartmentsAll = new ArrayList<>(departments);
        }
    
        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) {
                    FilterResults filterResults = new FilterResults();
                    List<Department> departmentsSuggestion = new ArrayList<>();
                    if (constraint != null) {
                        for (Department department : mDepartmentsAll) {
                            if (department.name.toLowerCase().startsWith(constraint.toString().toLowerCase())) {
                                departmentsSuggestion.add(department);
                            }
                        }
                        filterResults.values = departmentsSuggestion;
                        filterResults.count = departmentsSuggestion.size();
                    }
                    return 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);
                        for (Object object : (List<?>) results.values) {
                            if (object instanceof Department) {
                                mDepartments.add((Department) object);
                            }
                        }
                        notifyDataSetChanged();
                    } else if (constraint == null) {
                        // no filter, add entire original list back in
                        mDepartments.addAll(mDepartmentsAll);
                        notifyDataSetInvalidated();
                    }
                }
            };
        }
    }
    

    Main Activity:

    @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());
            }
        }
    

    Here's the screenshot:

    BNK's screenshot

    Hope this helps!