Amer Sbetey Amer Sbetey - 2 months ago 10
Android Question

how to Filter by Using SearcheView Widjet on ListFragment

Hello I am googling on that issue for long time but no solution
i have ListFragment that show data from SQlite
i want to build the option to filter by TextChange
i Added the widjet and its working perfect - but how to make the filter ??
getFilter().filter() is not enough .

this is fragmentList

public class CarGallery extends ListFragment {
public static final String ROW_ID = "row_id"; // Intent extra key
private int contentFrameId;
private SimpleCursorAdapter myCarSimpleCursorAdapter;
private SearchView searchView;
private SearchManager searchManager;
private Cursor cursor;
private String[] from;
private int[] to;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
contentFrameId= ((ViewGroup) getView().getParent()).getId();
// map each contact's name to a TextView in the ListView layout
from = new String[] {"number","manufacturer","model","img"};
// in file car_row.xml
to = new int[] {R.id.textViewNumber,R.id.textViewManufacturer,R.id.textViewModel,R.id.imageViewCar};
myCarSimpleCursorAdapter = new SimpleCursorAdapter(getActivity().getApplicationContext(),
R.layout.car_row, // layout to inflate it
null , // cursor adapter : if null then it will be created within the constructor
from , to , 0 );
myCarSimpleCursorAdapter.setViewBinder(new MyViewBinder());
setListAdapter(myCarSimpleCursorAdapter); //databinding --> set contactView's adapter
}
@Override
public void onResume() {
super.onResume();
// create new GetCarsTask and execute it
// our inner class
new GetCarTask().execute();// (Object[]) null

getActivity().setTitle(R.string.actionbarTitleGallery);
}
@Override
public void onStop() {
super.onStop();
cursor = myCarSimpleCursorAdapter.getCursor(); // get current Cursor
if (cursor != null)
cursor.deactivate(); // deactivate it
myCarSimpleCursorAdapter.changeCursor(null); // adapted now has no Cursor
}
////// performs database query outside GUI thread/////////////
private class GetCarTask extends AsyncTask<Void , Void , Cursor>{
DatabaseConnector databaseConnector = new DatabaseConnector(getActivity().getApplicationContext());
@Override
protected Cursor doInBackground(Void... voids) {
databaseConnector.open();
return databaseConnector.getAllCars();
}
@Override
protected void onPostExecute(Cursor result) {
myCarSimpleCursorAdapter.changeCursor(result);
databaseConnector.close();
}
}
/////// MyViewBinder Class////////////////////////////////
public class MyViewBinder implements SimpleCursorAdapter.ViewBinder {
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
int viewID = view.getId();
switch (viewID) {
case R.id.textViewNumber:
TextView carNumber = (TextView) view;
String car_number;
car_number = cursor.getString(cursor.getColumnIndex("number"));
carNumber.setText(car_number);
break:
case R.id.textViewManufacturer:
TextView carManufacturer = (TextView) view;
String car_manufacturer;
car_manufacturer = cursor.getString(cursor.getColumnIndex("manufacturer"));
carManufacturer.setText(car_manufacturer);
break;
case R.id.textViewModel:
TextView carModel = (TextView) view;
String car_model;
car_model = cursor.getString(cursor.getColumnIndex("model"));
carModel.setText(car_model);
break;
case R.id.imageViewCar:
ImageView carImageView = (ImageView) view;
byte[] imageBytes = cursor.getBlob(cursor.getColumnIndex("img"));
if (imageBytes != null) { carImageView.setImageBitmap(BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length));
} else {
// carImageView.setBackgroundResource(R.mipmap.ic_launcher);
}
break;
}
return true;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.search , menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
searchManager = (SearchManager)getActivity().getSystemService(Context.SEARCH_SERVICE); searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
if(searchItem != null){
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
// some opertion
return true;
}
});
searchView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//some operario
}
});
EditText searchPlate = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
searchPlate.setHint("Search");
View searchPlateView = searchView.findViewById(android.support.v7.appcompat.R.id.search_plate); searchPlateView.setBackgroundColor(ContextCompat.getColor(getActivity(), android.R.color.transparent));
// this method for search process
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
// this method when query submitted
Toast.makeText(getActivity(), s, Toast.LENGTH_SHORT).show();
return true;
}
@Override
public boolean onQueryTextChange(String s) {
// this method for auto complete search process
Toast.makeText(getActivity(), s, Toast.LENGTH_SHORT).show();
myCarSimpleCursorAdapter.getFilter().filter(s); return true;
}
});
}
}
}

Answer

For peaple that will have problems with that issue i am posting the best sloution.

Step 1 : Define empty simpleCursor Adapter

    public class CarGallery extends ListFragment {

        public static final String ROW_ID = "row_id"; // Intent extra key
        private SimpleCursorAdapter myCarSimpleCursorAdapter;
        private Cursor mCursor;
        private String[] from;
        private int[] to;

        @Override
        public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
            setHasOptionsMenu(true);
            // map each car details to a TextViews in the ListView layout
            from = new String[]{"number", "manufacturer", "model", "img"};
            // in file  car_row.xml
            to = new int[]{R.id.textViewNumber, R.id.textViewManufacturer, R.id.textViewModel, R.id.imageViewCar};
            //Create Empty Adapter
            myCarSimpleCursorAdapter = new SimpleCursorAdapter(getActivity().getApplicationContext(),
                    R.layout.car_row, // layout to inflate it
                    mCursor, // cursor adapter : if null then it will be created within the constructor
                    from, to, 0);

    // set the Adapter on ViewBinder Class 
            myCarSimpleCursorAdapter.setViewBinder(new MyViewBinder());
            setListAdapter(myCarSimpleCursorAdapter);  //databinding --> set contactView's adapter
}

Step 2 : Define the Filter method in DatabaseConnector after we created the table :

public class DatabaseConnector //DAL
{
    private static final String DATABASE_NAME = "UserCars";

    private DatabaseOpenHelper databaseOpenHelper;
    private SQLiteDatabase database;

    public Cursor getFilteredCars(CharSequence charSequence) {

        if (charSequence == null || charSequence.length() == 0) {
            return database.rawQuery("SELECT _id ,number, manufacturer , model ,  img FROM cars order by manufacturer", null);
        } else {
            String value = "%" + charSequence.toString() + "%";

            return database.rawQuery("SELECT _id , number , manufacturer , model ,img FROM cars WHERE  manufacturer || number || model like ?", new String[]{value});

        }

    }
}

Step 3 : Create the Search Widjet on Fragment Class

// creating the SearchView Widjet
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.search, menu);
        MenuItem searchItem = menu.findItem(R.id.action_search);

        SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
        SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));


        if (searchItem != null) {
            searchView = (SearchView) MenuItemCompat.getActionView(searchItem);

            searchView.setOnCloseListener(new SearchView.OnCloseListener() {
                @Override
                public boolean onClose() {
                    // some opertion

                    return true;
                }
            });
            searchView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //some operarion

                }
            });

            EditText searchPlate = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
            searchPlate.setHint("Search");
            View searchPlateView = searchView.findViewById(android.support.v7.appcompat.R.id.search_plate);
            searchPlateView.setBackgroundColor(ContextCompat.getColor(getActivity(), android.R.color.transparent));

            //  this method for search process
            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String s) {
                    //  this method when query submitted
                    myCarSimpleCursorAdapter.getFilter().filter(s);

                    return true;
                }

                @Override
                public boolean onQueryTextChange(String s) {
                    // this method for auto complete search process
                    myCarSimpleCursorAdapter.getFilter().filter(s);
                    return true;
                }
            });
        }
    }

With it"s XML

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ui.home.activities.TransactionSearchActivity">
    <item
        android:id="@+id/action_search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="Search"
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="ifRoom" />
</menu>

Step 4 : back to onViewCreate to setFilterQueryProvider , and create the method getCursor

// add this code to onViewCreate 
        myCarSimpleCursorAdapter.setFilterQueryProvider(new FilterQueryProvider() {
            @Override
            public Cursor runQuery(CharSequence charSequence) {
                return getCursor(charSequence.toString());


// create the getCursor that Include AsyncTask to get data on BackGround 

    private Cursor getCursor(String str) {
        class GetCarTask extends AsyncTask<CharSequence, Object, Cursor> {
            DatabaseConnector databaseConnector = new DatabaseConnector(getActivity().getApplicationContext());

            @Override
            protected Cursor doInBackground(CharSequence... charSequences) {
                databaseConnector.open();
                return databaseConnector.getFilteredCars(charSequences[0]);

            }

            @Override
            protected void onPostExecute(Cursor cursor) {
                super.onPostExecute(cursor);
                myCarSimpleCursorAdapter.changeCursor(cursor);
                databaseConnector.close();
            }

        }
        new GetCarTask().execute(new CharSequence[]{str});
        return null;

    } // end of getCursor

Step 5 : Finaly execute the Cursor with null in onResum sending null String wil show all the data befor the filtering and that's it .

@Override
public void onResume() {
    super.onResume();

    getActivity().setTitle(R.string.actionbarTitleGallery);
    mCursor = getCursor("");
}