android - Cómo crear BaseAdapter personalizado para AutoCompleteTextView
android-arrayadapter (2)
Clase BaseAdapter personalizada
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();
}
}
}
}
Clase de actividad principal
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);
}
}
Diseño desplegable
<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>
Mi lista original tiene datos tomados del servicio web, así que supongamos que ya tiene datos. Por supuesto, puede personalizar aún más el menú desplegable agregando más vistas, solo no olvide actualizar el adaptador para incorporar las nuevas vistas.
He tenido dificultades para crear un ArrayAdapter personalizado para AutoCompleteTextView, tales errores que aparecerían a pesar de que el siguiente código encontrado en Internet sería:
- El menú desplegable no aparecerá.
- Los objetos personalizados y sus detalles no aparecerían.
Entonces, para aquellos que tienen o tuvieron el mismo problema que yo, recomiendo usar BaseAdapter para AutoCompleteTextView en su lugar.
El siguiente es mi código de trabajo usando ArrayAdapter .
Supongamos que los datos de respuesta del servicio web tienen el siguiente aspecto:
[
{
"id": "1",
"name": "Information Technology"
},
{
"id": "2",
"name": "Human Resources"
},
{
"id": "3",
"name": "Marketing and PR"
},
{
"id": "4",
"name": "Research and Developement"
}
]
Luego en tu cliente Android:
Clase de departamento:
public class Department {
public int id;
public String name;
}
Clase de adaptador personalizado:
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();
}
}
};
}
}
Actividad principal:
@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());
}
}
Aquí está la captura de pantalla:
¡Espero que esto ayude!