How to create custom BaseAdapter for AutoCompleteTextView
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:
Hope this helps!
How to add a custom adapter to an AutoCompleteTextView
According to the documentation, the inferred type of setAdapter in AutoCompleteTextView is :
<T extends ListAdapter & Filterable> void setAdapter(T adapter)
Your adapter must be a ListAdapter (which BaseAdapter is, so far so good) and a Filterable, which BaseAdapter is not, nor is your Adapter implementation. I would extend an ArrayAdapter, which is Filterable, not to mention is would simplify your implementation (some of your methods duplicate methods of ArrayAdapter for the same result) :
public class TwoLineDropdownAdapter extends ArrayAdapter<TwoLineDropDown> {
private LayoutInflater mInflater = null;
private Activity activity;
public TwoLineDropdownAdapter(Activity a, ArrayList<TwoLineDropDown> items) {
super(a, 0, items);
activity = a;
mInflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public static class ViewHolder {
public TextView title;
public TextView description;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.dropdown_text_twoline,
parent, false);
holder.title = (TextView) convertView
.findViewById(R.id.text1);
holder.description = (TextView) convertView
.findViewById(R.id.text2);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
android: AutoCompleteTextView with custom adapter
// try this
autoCompleteText.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View arg1, int position, long arg3) {
String str = (String) adapterView.getItemAtPosition(position);
autoCompleteText.setText(str);
}
});
MultiAutoCompleteTextView with custom adapter (BaseAdapter)
You need to setTokenizer()
to your MultiAutoCompleteTextView
in order to get it work.
You can use -
textView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
Even you can set your own custom tokenizer if you have any special requirements else you can use CommaTokenizer
which appends comma(,) everytime you select any option from the dropdown.
Autocompletetextview with custom adapter and filter
Okay i think i figure out what Luksprog was saying this code works now they key is this
mContactList = (ArrayList<Map<String, String>>) results.values;
in
@Override
public int getCount(){
return mContactList.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.auto_contact_list, parent,
false);
TextView nameView = (TextView) rowView.findViewById(R.id.ccontName);
TextView phoneView = (TextView) rowView.findViewById(R.id.ccontNo);
TextView typeView = (TextView) rowView.findViewById(R.id.ccontType);
Map<String, String> contactMap = mContactList.get(position);
nameView.setText(contactMap.get("name"));
phoneView.setText(contactMap.get("phone"));
typeView.setText(contactMap.get("type"));
return rowView;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (results.count > 0) {
mContactList = (ArrayList<Map<String, String>>) results.values;
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<Map<String, String>> result = new ArrayList<Map<String, String>>();
HashMap<String,String> myMap = new HashMap<String,String>();
myMap.put("name", "key");
result.add(myMap);
HashMap<String,String> myMap2 = new HashMap<String,String>();
myMap2.put("name", "is");
result.add(myMap2);
HashMap<String,String> myMap3 = new HashMap<String,String>();
myMap3.put("name", "another");
result.add(myMap3);
FilterResults r = new FilterResults();
r.values = result;
r.count = result.size();
return r;
}
};
}
How to use a custom adapter for AutoCompleteTextView
You are giving reference over here,
ArrayList<String> mData = mList;
ArrayList<String> mSuggestions = mList;
And then clearing it,
mSuggestions.clear();
That's why loop has no data and it was not working.
Instead declare new object, like this,
ArrayList<String> mData = new ArrayList<String>(mList);
ArrayList<String> mSuggestions = new ArrayList<String>(mList);
Android: Set AutoCompleteTextView with a custom adapter
Make sure your adapter implements the Filterable
interface.
public class CustomCardListAdapter extends BaseAdapter implements Filterable
AutoCompleteTextView does not work with custom ArrayAdapter
In your custom ArrayAdapter
class, you need to override public Filter getFilter()
I have a working sample code at the following question, please take a look:
How to create custom BaseAdapter for AutoCompleteTextView
Hope this helps!
Related Topics
What's Oncreate(Bundle Savedinstancestate)
Add "View More" at the End of Textview After 3 Lines
Android App Crashes When Launched in Debug Mode
Determine Addaction Click for Android Notifications
Sniffing/Logging Your Own Android Bluetooth Traffic
How to Set a Particular Font for a Button Text in Android
Android Edittext - Finished Typing Event
How to Use Custom Permissions in Android
How to Use Getsystemservice in a Non-Activity Class (Locationmanager)
Drawerlayout Double Drawer (Left and Right Drawers Simultaneously)
How to Create a Resizable Rectangle with User Touch Events on Android
How to Set a Font for the Options Menu
Add a Header to a Gridview (Android)
Detecting Sms Incoming and Outgoing
Android: How to Get Value of an Attribute in Code
How to Re-Sign an .Apk with a Different Certificate Than What It Came With