I am developing an app in which I have used a 'Recyclerview', and I have successfully implemented Search(Using SearchView in Toolbar), Filtering(Using Custom Dialog with Filter Inputs) and Sorting (Price Low to High and High to Low).
Now the problem I have encountered is that whenever I sort the list before searching something or filtering, Sorting works fine. But after searching something or filtering, Sorting is not working. I have searched a lot but couldn't find a solution.
Here is the only SO question related to my problem but I can't solve my problem with answers provided: Recyclerview - Sorting not working after searching an 'Arraylist'
PS: I have deleted the code to include only related code.
Recyclerview Adapter:
public class TripListRecyclerViewAdapter extends RecyclerView.Adapter<TripListRecyclerViewAdapter.ViewHolder> implements Filterable {
private static final String TAG = TripListRecyclerViewAdapter.class.getSimpleName();
private Context mContext;
private ArrayList<Trip> mTrips = new ArrayList<>();
private ArrayList<Trip> mTripsFiltered = new ArrayList<>();
public TripListRecyclerViewAdapter(Context mContext, ArrayList<Trip> mTrips) {
this.mContext = mContext;
this.mTrips = mTrips;
this.mTripsFiltered = mTrips;
}
@Override
public int getItemCount() {
return mTripsFiltered.size();
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
mTripsFiltered = mTrips;
} else if (charString.contains("Min") && charString.contains("Max")) {
String minPrice = charString.substring(3, charString.indexOf("Max"));
String maxPrice = charString.substring(charString.indexOf("Max") + 3);
ArrayList<Trip> filteredList = new ArrayList<>();
for (Trip trip : mTrips) {
if (trip.getTrip_rate() >= Integer.parseInt(minPrice) && trip.getTrip_rate() <= Integer.parseInt(maxPrice)) {
filteredList.add(trip);
}
}
mTripsFiltered = filteredList;
} else if (charString.contains("Min")) {
String minPrice = charString.substring(3);
ArrayList<Trip> filteredList = new ArrayList<>();
for (Trip trip : mTrips) {
if (trip.getTrip_rate() >= Integer.parseInt(minPrice)) {
filteredList.add(trip);
}
}
mTripsFiltered = filteredList;
} else if (charString.contains("Max")) {
String maxPrice = charString.substring(3);
ArrayList<Trip> filteredList = new ArrayList<>();
for (Trip trip : mTrips) {
if (trip.getTrip_rate() <= Integer.parseInt(maxPrice)) {
filteredList.add(trip);
}
}
mTripsFiltered = filteredList;
} else {
ArrayList<Trip> filteredList = new ArrayList<>();
for (Trip trip : mTrips) {
if (trip.getTrip_name().toLowerCase().contains(charString.toLowerCase()) || trip.getTrip_destination().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(trip);
}
}
mTripsFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mTripsFiltered;
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mTripsFiltered = (ArrayList<Trip>) filterResults.values;
notifyDataSetChanged();
}
};
}
}
Model for Sorting:
public class Trip implements Serializable {
public static final Comparator<Trip> PRICE_LOW_TO_HIGH = new Comparator<Trip>() {
@Override
public int compare(Trip tripOne, Trip tripTwo) {
Float tripRateOne = new Float(tripOne.trip_rate);
Float tripRateTwo = new Float(tripTwo.trip_rate);
return tripRateOne.compareTo(tripRateTwo);
}
};
public static final Comparator<Trip> PRICE_HIGH_TO_LOW = new Comparator<Trip>() {
@Override
public int compare(Trip tripOne, Trip tripTwo) {
Float tripRateOne = new Float(tripOne.trip_rate);
Float tripRateTwo = new Float(tripTwo.trip_rate);
return tripRateTwo.compareTo(tripRateOne);
}
};
public static final Comparator<Trip> DATE_NEW_TO_OLD = new Comparator<Trip>() {
@Override
public int compare(Trip tripOne, Trip tripTwo) {
Integer tripRateOne = new Integer(tripOne.trip_id);
Integer tripRateTwo = new Integer(tripTwo.trip_id);
return tripRateTwo.compareTo(tripRateOne);
}
};
@SerializedName("booking_id")
@Expose
private int booking_id;
@SerializedName("trip_rate")
@Expose
private float trip_rate;
public Trip(int booking_id) {
this.booking_id = booking_id;
}
public int getBooking_id() {
return booking_id;
}
public void setBooking_id(int booking_id) {
this.booking_id = booking_id;
}
}
Activity of Recyclerview:
mSortingTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Creating A Popup Menu
PopupMenu popupMenu = new PopupMenu(TripsActivity.this, mSortingTextView);
// Inflating Menu From XML Resource
popupMenu.inflate(R.menu.trip_sorting_menu);
// Adding Click Listener
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.latest:
// Handle Latest Click
mSortingTextView.setText("Latest");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.DATE_NEW_TO_OLD);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
case R.id.price_low_to_high:
// Handle Price (Low to High) Click
mSortingTextView.setText("Price (Low to High)");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.PRICE_LOW_TO_HIGH);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
case R.id.price_high_to_low:
// Handle Price (High to Low) Click
mSortingTextView.setText("Price (High to Low)");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.PRICE_HIGH_TO_LOW);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
case R.id.date_new_to_old:
// Handle Date (New to Old) Click
mSortingTextView.setText("Date (New to Old)");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.DATE_NEW_TO_OLD);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
});
// Displaying The Popup Menu
popupMenu.show();
}
});
mFilterTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(TripsActivity.this);
dialogBuilder.setTitle("Filters");
dialogBuilder.setCancelable(false);
LayoutInflater layoutInflater = TripsActivity.this.getLayoutInflater();
View dialogView = layoutInflater.inflate(R.layout.filter_dialog, null);
dialogBuilder.setView(dialogView);
TextInputLayout minPriceTextInputLayout = (TextInputLayout) dialogView.findViewById(R.id.minimum_price_text_input_layout);
TextInputLayout maxPriceTextInputLayout = (TextInputLayout) dialogView.findViewById(R.id.maximum_price_text_input_layout);
dialogBuilder.setPositiveButton("DONE", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialogBuilder.setNegativeButton("RESET", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
String reset = "";
if (mTripListRecyclerViewAdapter != null) {
mTripListRecyclerViewAdapter.getFilter().filter(reset);
}
}
});
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String minPrice = minPriceTextInputLayout.getEditText().getText().toString().trim();
String maxPrice = maxPriceTextInputLayout.getEditText().getText().toString().trim();
if (minPrice.equals("") && maxPrice.equals("")) {
alertDialog.dismiss();
} else {
String price = "";
if (minPrice.length() > 0 && maxPrice.length() > 0) {
if (Integer.parseInt(minPrice) > Integer.parseInt(maxPrice)) {
minPriceTextInputLayout.setError("Minimum Price should be less than Maximum Price");
} else {
price = "Min" + minPrice + "Max" + maxPrice;
alertDialog.dismiss();
}
} else if (minPrice.length() > 0) {
price = "Min" + minPrice;
alertDialog.dismiss();
} else if (maxPrice.length() > 0) {
price = "Max" + maxPrice;
alertDialog.dismiss();
}
if (mTripListRecyclerViewAdapter != null) {
mTripListRecyclerViewAdapter.getFilter().filter(price);
}
}
}
});
}
});
I solved the above posted problem by Sorting both ArrayList
Original and Filtered one.
Here are the changes I made:
Recyclerview Adapter:
public ArrayList<Trip> mTripsFiltered = new ArrayList<>();
Activity of Recyclerview:
// Adding Click Listener
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.latest:
// Handle Latest Click
mSortingTextView.setText("Latest");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.DATE_NEW_TO_OLD);
Collections.sort(mTripListRecyclerViewAdapter.mTripsFiltered, Trip.DATE_NEW_TO_OLD);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
case R.id.price_low_to_high:
// Handle Price (Low to High) Click
mSortingTextView.setText("Price (Low to High)");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.PRICE_LOW_TO_HIGH);
Collections.sort(mTripListRecyclerViewAdapter.mTripsFiltered, Trip.PRICE_LOW_TO_HIGH);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
case R.id.price_high_to_low:
// Handle Price (High to Low) Click
mSortingTextView.setText("Price (High to Low)");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.PRICE_HIGH_TO_LOW);
Collections.sort(mTripListRecyclerViewAdapter.mTripsFiltered, Trip.PRICE_HIGH_TO_LOW);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
case R.id.date_new_to_old:
// Handle Date (New to Old) Click
mSortingTextView.setText("Date (New to Old)");
if (mTrips.size() > 0) {
Collections.sort(mTrips, Trip.DATE_NEW_TO_OLD);
Collections.sort(mTripListRecyclerViewAdapter.mTripsFiltered, Trip.DATE_NEW_TO_OLD);
}
mTripListRecyclerViewAdapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.