0

Let's say I have web-request for a list of meals and implemented using a Recyclerview, now what if I want to sort/move specific items at the top..!


Meal: Italian Pasta | Type: pasta | Price: 20$

Meal: Hotdogs Pizza | Type: pizza | Price: 10$

Meal: Burger | Type: fast food | Price: 30$

Meal: Rice | Type: lunch | Price: 18$

Meal: Mac & Cheese | Type: lunch | Price: 17$

Meal: CheeseBurger | Type: fast food | Price: 8$


So for example, what I want is for every item who has a type of fast food and pizza to show at the top of the list and then the rest..!?

where do I perform this sorting logic, is it inside the adapter or the activity of the recyclerview? is there like an existing method for this function like moveToTop() to be used like this:

for(Meals item: dataList){

   if (item.getType.equals("fast food") || item.getType.equals("pizza")){
      item.moveToTop(); 
   }

}

Is it possible?


Update 2

I figured out, I found a method a special parameter of interface for the recyclerview in these situations SortedListAdapterCallback

if (homeData.size() > 0) {

            Collections.sort(homeData, Collections.reverseOrder(new SortedListAdapterCallback<HomeItemModel>(adapter) {
              @Override
              public int compare(HomeItemModel o1, HomeItemModel o2) {

               int weight1;
               int weight2;

               if(item1.getType.equals("fast food") || item1.getType.equals("pizza")){
                   weight1 = 1;
               }else{
                   weight1 = 0;
               }

               if(item2.getType.equals("fast food") || item2.getType.equals("pizza")){
                weight2 = 1;
               }else{
                weight2 = 0;
               }

                if (weight1 == weight2)
                   return 0;
                else if (weight1 > weight2)
                   return 1;
                else
                   return -1;

                 }

              @Override
              public boolean areContentsTheSame(HomeItemModel oldItem, HomeItemModel newItem) {
                return false;
              }

              @Override
              public boolean areItemsTheSame(HomeItemModel item1, HomeItemModel item2) {
                return false;
              }
            }));

          }

The only problem here, is the order at the top..! they show like this:

  • fast food
  • pizza
  • pizza
  • fast food
  • pizza
  • fast food
  • ... the rest of the list

I want them to show ordered.. like this:

  • fast food // or the pizzas first
  • fast food
  • fast food
  • pizza
  • pizza
  • pizza
  • ... the rest of the list

Can this be done..?

Alaa AbuZarifa
  • 1,171
  • 20
  • 39
  • You have to sort your list. How you decide to do that is up to you – bogdanN Sep 13 '17 at 13:05
  • Have a look at this answer : https://stackoverflow.com/questions/42054262/best-way-to-sort-a-list-using-two-different-fields Though it is not android specific but it may help you – chetan Sep 14 '17 at 07:23

2 Answers2

2

Create a Comparator inside your POJO class Meals

public static class CustomComparator implements Comparator<Meals> {
    public int compare(Meals  item1, Meals  item2) {

        int weight1;
        int weight2;

        if(item1.getType.equals("fast food") || item1.getType.equals("pizza")){
            weight1 = 1;
        }else{
            weight1 = 0;
        }

        if(item2.getType.equals("fast food") || item2.getType.equals("pizza")){
            weight2 = 1;
        }else{
            weight2 = 0;
        }


        if (weight1 == weight2)
            return 0;
        else if (weight1 > weight2)
            return 1;
        else
            return -1;
    }
}

And before setting your adapter call this line then pass the data list into your Adapter constructor.

Collections.sort(yourDataLIst, Collections.reverseOrder(new Meals.CustomComparator()));

EDIT If you want to all fast food first then pizza and then all the list then just tweak your sort logic as below

        if(item1.getType.equals("fast food")){
            weight1 = 2;
        }else if (item1.getType.equals("pizza")){
            weight1 = 1;
        } else {
            weight1 = 0;
        }

        if(item2.getType.equals("fast food")){
            weight2 = 2;
        }else if (item2.getType.equals("pizza")){
            weight2 = 1;
        } else{
            weight2 = 0;
        }
Kunu
  • 5,078
  • 6
  • 33
  • 61
  • not working, the list wasn't ordered? are you sure about this logic? – Alaa AbuZarifa Sep 13 '17 at 13:26
  • List doesn't have to be ordered. `sort` function will sort them according to your Comparator logic. And you can check the logic by yourself whether you want something like this or not? – Kunu Sep 13 '17 at 13:29
  • I solved it, approve the edit.. could you help with the slight problem with the solution..! – Alaa AbuZarifa Sep 14 '17 at 09:23
  • Post last part in your question – Kunu Sep 14 '17 at 09:25
  • I'm having a problem, in the example.. the types of meals are set manually, but in my real code they are not. First, it's hobbies not meal types and the user can select from a list of them once the app gets launched and in the next screen the selected hobbies will show at the top from data list, then the rest..! I tried a few soulton but they didn't work, the one in this gist here, it only show the first item in the hobbies arraylist and ignores the other selected.!? please help me with this.. https://gist.github.com/AlaaZarifa/f03400c35f32288eb9f5b25391aed2de – Alaa AbuZarifa Sep 15 '17 at 16:49
  • How are you ensuring which will go on top? You must be storing somewhere those values. – Kunu Sep 16 '17 at 07:31
  • I'm not, but It's okay I solved after a lot of tries..! I removed the `for-each` and replaced the other condition with "contains" and it worked :D check the gist. I updated it. – Alaa AbuZarifa Sep 16 '17 at 10:06
0

There is no simple method like moveToTop() in Arraylist. But you can shift the data manually.

You can do that like this:

for(Meals item: dataList){

   if (item.getType.equals("fast food") || item.getType.equals("pizza")){
      int index = dataList.indexOf(item);
      dataList.remove(index);
      dataList.add(0, item);
      adapter.notifyDataSetChanged()
   }

}

Hope it helps:)

Bhuvanesh BS
  • 13,474
  • 12
  • 40
  • 66
  • didn't work, I put it inside the activity after setting the recyclerview to the adapter~! should it be elsewhere !? – Alaa AbuZarifa Sep 13 '17 at 13:31
  • to update UI you have to call 'notifyDataSetChanged()'. See my answer. If it is not resolved your issue post your activity code. – Bhuvanesh BS Sep 13 '17 at 13:38
  • it only showed the one item at the top, not all of them..? something missing in the for loop maybe? see the Update for the code..! – Alaa AbuZarifa Sep 14 '17 at 07:10