Filter a ListView on an Android CursorAdapter

0

Hello friends I wanted to see if you can help me, I'm with the following problem. I have in a fragment a listview to which I charge the information for a Cursor Adapter. Now what I want is to be able to filter that list.

In the fragment in the method onCreateOptionsMenu I have the following

public class ArticulosFragment extends Fragment {
private static final String ARG_PRECIO_ID = "precioId";
private OperacionesBaseDatos mOpebase;
private ListView mArticulosList;
private ArticulosCursorAdapter mArticulosAdapter;
private String mPrecioId;

public ArticulosFragment() {
    // Required empty public constructor
}


public static ArticulosFragment newInstance(String precioId) {
    ArticulosFragment fragment = new ArticulosFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PRECIO_ID, precioId);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //obtenemos el codigo del precio seleccionado para los items
    if (getArguments() != null) {
        mPrecioId = getArguments().getString(ARG_PRECIO_ID);
        if (mPrecioId==null) {
            mPrecioId=getResources().getString(R.string.precio_default);
        }
    }
    //habilitamos el toolbar
    setHasOptionsMenu(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_articulos, container, false);

    //referencias UI
    mArticulosList = (ListView) root.findViewById(R.id.articulos_list);
    mArticulosAdapter = new ArticulosCursorAdapter(getActivity(),null);
    mArticulosList.setAdapter(mArticulosAdapter);

    // Eventos
    mArticulosList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            Cursor currentItem = (Cursor) mArticulosAdapter.getItem(i);
            String currentItemId = currentItem.getString(currentItem.getColumnIndex(ContratoPedidos.Productos.ID));
            String currentItemCod = currentItem.getString(currentItem.getColumnIndex(ContratoPedidos.Productos.CODIGO));
            Float currentPrecio = currentItem.getFloat(currentItem.getColumnIndex(ContratoPedidos.Productos.PRECIO));
            ShowCantidadItems(currentItemId,currentItemCod,currentPrecio);
        }
    });

    LoadArticulos();
    return root;
}



//
//Metodo para revisar el texto del filtro
//

@Override
public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) {
    //super.onCreateOptionsMenu(menu, inflater);

    menu.clear();
    inflater.inflate(R.menu.menu_buscar_articulos,menu);
    final MenuItem searchItem = menu.findItem(R.id.mnu_articulo_buscar);
    final SearchView searchView = (SearchView) searchItem.getActionView();
    searchView.setQueryHint("Buscar Articulo");
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
        @Override
        public boolean onQueryTextSubmit(String query) {

            query=query.toUpperCase();
            //mArticulosAdapter.getFilterQueryProvider

            mArticulosAdapter.setFilterQueryProvider(new FilterQueryProvider() {
                public Cursor runQuery(CharSequence constraint) {
                    return mOpebase.ObtenerInstancia(getActivity()).BuscarProductosPorDescripcion(mPrecioId,"LAVA");
                }
            });
            Cursor xx = mOpebase.ObtenerInstancia(getActivity()).ObtenerProductosPorPrecio(mPrecioId);
            //mArticulosAdapter.getFilter().filter(query);
            mArticulosAdapter.notifyDataSetChanged();
            Toast.makeText(getActivity(),query,Toast.LENGTH_LONG).show();
            return false;
        }
        @Override
        public boolean onQueryTextChange(String newText) {
            if (!TextUtils.isEmpty(newText)) {
                AplicarFiltro(newText);
                mArticulosList.setFilterText(newText);
            }
            //searchView.setQuery("", false);
            //searchView.setIconified(true);
            return false;
        }



    });


    super.onCreateOptionsMenu(menu,inflater);
}

private void AplicarFiltro(String newText) {
    ArticulosCursorAdapter adapter = (ArticulosCursorAdapter) mArticulosList.getAdapter();
    //adapter.filter(newText);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == PedidosCrearFragment.REQUEST_UPDATE_DELETE_PEDIDO) {
        if (resultCode == Activity.RESULT_OK) {
            String id=data.getStringExtra("idArticulo");
            String cod=data.getStringExtra("codiArticulo");
            String des=data.getStringExtra("descArticulo");
            Integer cant=data.getIntExtra("canIngresada",0);
            Float pre=data.getFloatExtra("precioArticulo",0);
            Integer desc=data.getIntExtra("porDescuento",0);

            Intent intentArt = new Intent();
            intentArt.putExtra("idArticulo",id);
            intentArt.putExtra("codiArticulo",cod);
            intentArt.putExtra("descArticulo",des);
            intentArt.putExtra("canIngresada",cant);
            intentArt.putExtra("precioArticulo",pre);
            intentArt.putExtra("porDescuento",desc);
            getActivity().setResult(Activity.RESULT_OK,intentArt);
            getActivity().finish();
        }
    }
}


private void  LoadArticulos(){
    new ArticulosLoadTask().execute();
}

private class ArticulosLoadTask extends AsyncTask<Void, Void, Cursor> {

    @Override
    protected Cursor doInBackground(Void... voids) {
        return mOpebase.ObtenerInstancia(getActivity()).ObtenerProductosPorPrecio(mPrecioId);
    }

    @Override
    protected void onPostExecute(Cursor cursor) {
        if (cursor != null && cursor.getCount() > 0) {
            mArticulosAdapter.swapCursor(cursor);
        } else {
            // Mostrar empty state
            Toast.makeText(getActivity(),"No hay articulos en la lista de precio seleccionada",Toast.LENGTH_LONG).show();
        }
    }
}

private void ShowCantidadItems(String itemId,String itemCod,Float precio) {
    Intent intent = new Intent(getActivity(), ArticuloAgregarCantidadActivity.class);
    intent.putExtra(ArticulosActivity.EXTRA_ARTICULO_ID, itemId);
    intent.putExtra(ArticulosActivity.EXTRA_ARTICULO_COD, itemCod);
    intent.putExtra(ArticulosActivity.EXTRA_ARTICULO_CANTIDAD, 0);
    intent.putExtra(ArticulosActivity.EXTRA_PRECIO, precio);
    startActivityForResult(intent, PedidosCrearFragment.REQUEST_UPDATE_DELETE_PEDIDO);
}

}

In onQueryTextSubmit , I have the text that the user types in the query variable, but I do not know how to apply the filter here.

My adapter cursor is the following

import android.content.Context;
import android.database.Cursor;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import saga.com.ec.sagamovil.R;
import saga.com.ec.sagamovil.sqlite.ContratoPedidos;

/**
 * Created by fsigu on 23/1/2017.
 */

public class ArticulosCursorAdapter extends CursorAdapter implements Filterable {

public ArticulosCursorAdapter(Context context, Cursor c) {
    super(context, c, 0);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(context);
    return  inflater.inflate(R.layout.list_item_articulo,parent,false);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    //referencias UI
    TextView articuloText = (TextView) view.findViewById(R.id.tv_articulo);
    TextView cantidadText = (TextView) view.findViewById(R.id.tv_cantidad_articulo);
    TextView precioText = (TextView) view.findViewById(R.id.tv_precio_articulo);

    //get valores
    String codigo=cursor.getString(cursor.getColumnIndex(ContratoPedidos.Productos.CODIGO));
    String articulo=cursor.getString(cursor.getColumnIndex(ContratoPedidos.Productos.NOMBRE));
    String existencia=cursor.getString(cursor.getColumnIndex(ContratoPedidos.Productos.SALDO));
    String precio=cursor.getString(cursor.getColumnIndex(ContratoPedidos.Productos.PRECIO));

    //setup
    articuloText.setText(articulo);
    cantidadText.setText(existencia);
    precioText.setText(precio);
}

@Override
public Filter getFilter() {

    Filter filter = new Filter() {

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {

            List<String> arrayListNames = (List<String>) results.values;
            notifyDataSetChanged();
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            FilterResults results = new FilterResults();
            ArrayList<String> FilteredArrayNames = new ArrayList<String>();

            // perform your search here using the searchConstraint String.

            constraint = constraint.toString().toLowerCase();
            for (int i = 0; i < mDatabaseOfNames.size(); i++){
                String dataNames = mDatabaseOfNames.get(i);
                if (dataNames.toLowerCase().startsWith(constraint.toString()))  {
                    FilteredArrayNames.add(dataNames);
                }
            }

            results.count = FilteredArrayNames.size();
            results.values = FilteredArrayNames;
            Log.e("VALUES", results.values.toString());

            return results;
        }
    };

    return filter;
}
}

I do not know if you can help me because I have tried several ways and I do not know how to apply the filter.

Greetings

    
asked by fsigu 27.07.2017 в 18:27
source

1 answer

0

It seems to me that what you need is to implement the Filterable interface on your adapter and its methods, which you should take into account is the getFilter, since in it you will work the CharSecuences that you will filter and the array to filter:

public class ArticulosCursorAdapter extends CursorAdapter implements Filterable{
    ...

    @Override
    public Filter getFilter() {

        Filter filter = new Filter() {

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

                arrayListNames = (List<String>) results.values;
                notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                FilterResults results = new FilterResults();
                ArrayList<String> FilteredArrayNames = new ArrayList<String>();

                // perform your search here using the searchConstraint String.

                constraint = constraint.toString().toLowerCase();
                for (int i = 0; i < mDatabaseOfNames.size(); i++) {
                    String dataNames = mDatabaseOfNames.get(i);
                    if (dataNames.toLowerCase().startsWith(constraint.toString()))  {
                        FilteredArrayNames.add(dataNames);
                    }
                }

                results.count = FilteredArrayNames.size();
                results.values = FilteredArrayNames;
                Log.e("VALUES", results.values.toString());

                return results;
            }
        };

        return filter;
    }
}

And in the class that you implement the Adapter you do the same thing that you already have:

 @Override
 public boolean onQueryTextSubmit(String query) {
     ...
     mArticulosAdapter.getFilter().filter(query);
     ...
 }
    
answered by 27.07.2017 в 19:21