tutorial tipos studio personalizado filtrar dinamico desplegable columnas adaptadores android listview filter adapter

android - tipos - Filtrado de ListView con adaptador personalizado(objeto)



listview dinamico android studio (4)

Estoy tratando de implementar el filtrado de un ListView que utiliza un adaptador de objeto personalizado, pero no puedo encontrar ninguna muestra útil. El código incluido está muy simplificado, así que no, tenga en cuenta que no puedo usar un ArrayAdapter regular. Tengo un EditText encima de ListView, y cuando el usuario ingresa texto en el widget EditText me gustaría filtrar el ListView por el texto escrito en EditText. ¡Cualquier sugerencia sería muy apreciada!

Aquí está el fragmento de la clase de actividad:

public class management_objects extends Activity { private static List<User> UserList; private EfficientAdapter adapter = null; private ListView objectListView = null; private EditText SearchText = null; private static class EfficientAdapter extends BaseAdapter implements Filterable{ private LayoutInflater mInflater; public EfficientAdapter(Context context) { mInflater = LayoutInflater.from(context); } public int getCount() { return UserList.size(); } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.imagelayout_2lines, null); holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.managementObjectText); holder.subtext = (TextView) convertView.findViewById(R.id.managementObjectSubText); holder.icon = (ImageView) convertView.findViewById(R.id.managementObjectIcon); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.text.setText(UserList.get(position).getFirstName()); holder.subtext.setText(UserList.get(position).getLastName()); holder.icon.setImageResource(R.drawable.user); return convertView; } static class ViewHolder { TextView text; TextView subtext; ImageView icon; } @Override public Filter getFilter() { return null; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.adobjectlist); Bundle extras = getIntent().getExtras(); SearchText = (EditText) findViewById(R.id.SearchBox); SearchText.addTextChangedListener(filterTextWatcher); objectListView = (ListView) findViewById(R.id.ObjectList); objectListView.setOnItemClickListener(Item_Click); adapter = new EfficientAdapter(this); ComputerName = extras.getString("COMPUTER_NAME"); //Get User list from webservice ShowUsers(); }

Aquí está la clase de usuario:

public class User { private int UserId; private String FirstName; private String LastName; public int getUserId() { return UserId; } public void setUserId(int UserId) { this.UserId = UserId; } public String getFirstName() { return FirstName; } public void setFirstName(String FirstName) { this.FirstName = FirstName; } public String getLastName() { return LastName; } public void setLastName(String LastName) { this.LastName = LastName; } }


Agregue aString la anulación en su clase base. Por ejemplo

@Override public String toString() { return this.name; }

Arriba hace su lista como lista de cuerdas. Entonces puedes usar:

your_edit_text.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { YourActivity.this.YourAdapter.getFilter().filter(arg0); } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } @Override public void afterTextChanged(Editable arg0) { } });


Aquí un ejemplo interesante

public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { final FilterResults oReturn = new FilterResults(); final ArrayList<station> results = new ArrayList<station>(); if (orig == null) orig = items; if (constraint != null) { if (orig != null && orig.size() > 0) { for (final station g : orig) { if (g.getName().toLowerCase() .contains(constraint.toString())) results.add(g); } } oReturn.values = results; } return oReturn; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { items = (ArrayList<station>) results.values; notifyDataSetChanged(); } }; } public void notifyDataSetChanged() { super.notifyDataSetChanged(); notifyChanged = true; }


Necesitas hacer algunas cosas:

1) En su actividad, regístrese para un oyente de cambio de texto en su EditText que contiene el valor que ingresa el usuario:

mSearchValue.addTextChangedListener (searchTextWatcher);

2) Crea tu searchTextWatcher y haz que haga algo:

private TextWatcher searchTextWatcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // ignore } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // ignore } @Override public void afterTextChanged(Editable s) { Log.d(Constants.TAG, "*** Search value changed: " + s.toString()); adapter.getFilter().filter(s.toString()); } };

3) Anule getFilter () en su adaptador personalizado y haga que filtre los resultados y notifique a la vista de lista que el conjunto de datos ha cambiado.

@Override public Filter getFilter() { return new Filter() { @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { Log.d(Constants.TAG, "**** PUBLISHING RESULTS for: " + constraint); myData = (List<MyDataType>) results.values; MyCustomAdapter.this.notifyDataSetChanged(); } @Override protected FilterResults performFiltering(CharSequence constraint) { Log.d(Constants.TAG, "**** PERFORM FILTERING for: " + constraint); List<MyDataType> filteredResults = getFilteredResults(constraint); FilterResults results = new FilterResults(); results.values = filteredResults; return results; } }; }


Para aquellos que no necesitan la interfaz Filterable , hay una solución mucho más simple. Esto también maneja notifyDataSetChanged() correctamente donde las otras soluciones fallan. Tenga en cuenta que debe agregar una función getArray() al BaseAdapter que solo devuelve el objeto de matriz que se pasó al constructor.

public abstract class BaseFilterAdapter<T> extends BaseAdapter<T> { private List<T> original; private String lastFilter; public BaseFilterAdapter(Context context, List<T> array) { super(context, new LinkedList<T>()); original = array; filter(""); } protected abstract Boolean predicate(T element, String filter); public void filter(String filter) { lastFilter = filter; super.getArray().clear(); for (T element : original) if (predicate(element, filter)) super.getArray().add(element); super.notifyDataSetChanged(); } @Override public List<T> getArray() { return original; } @Override public void notifyDataSetChanged() { filter(lastFilter); } }