Divide Elements on Groups in Recyclerview or Grouping Recyclerview Items ,Say by Date

Divide elements on groups in RecyclerView or Grouping Recyclerview items ,say by date

Here is a solution i came by with the aid of alot research over the net and this blog link as well Kartikey Kuswhaha so its not all my credit but i just want to give more clarity to it.
below is the code:
create the following files:PojoOfJsonArray,MainActivity, ListItem ,GeneralItem ,DateItem , Adapter

PojoOfJsonArray.java -this file wil represent your POJO class or whatever pojo you got going on in your app so:

 public class PojoOfJsonArray  {

public PojoOfJsonArray(String name, String date) {
this.name = name;
this.date = date;
}

private String name,date;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}
}

MainActivity.java this is the activity that you will use to implement you recyclerview :

public class MainActivity extends AppCompatActivity {
private List<PojoOfJsonArray> myOptions = new ArrayList<>();
List<ListItem> consolidatedList = new ArrayList<>();

private RecyclerView mRecyclerView;
private Adapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mRecyclerView.setHasFixedSize(true);

myOptions.add(new PojoOfJsonArray("name 1", "2016-06-21"));
myOptions.add(new PojoOfJsonArray("name 2", "2016-06-05"));
myOptions.add(new PojoOfJsonArray("name 2", "2016-06-05"));
myOptions.add(new PojoOfJsonArray("name 3", "2016-05-17"));
myOptions.add(new PojoOfJsonArray("name 3", "2016-05-17"));
myOptions.add(new PojoOfJsonArray("name 3", "2016-05-17"));
myOptions.add(new PojoOfJsonArray("name 3", "2016-05-17"));
myOptions.add(new PojoOfJsonArray("name 2", "2016-06-05"));
myOptions.add(new PojoOfJsonArray("name 3", "2016-05-17"));

HashMap<String, List<PojoOfJsonArray>> groupedHashMap = groupDataIntoHashMap(myOptions);

for (String date : groupedHashMap.keySet()) {
DateItem dateItem = new DateItem();
dateItem.setDate(date);
consolidatedList.add(dateItem);

for (PojoOfJsonArray pojoOfJsonArray : groupedHashMap.get(date)) {
GeneralItem generalItem = new GeneralItem();
generalItem.setPojoOfJsonArray(pojoOfJsonArray);//setBookingDataTabs(bookingDataTabs);
consolidatedList.add(generalItem);
}
}

adapter = new Adapter(this, consolidatedList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(adapter);

}

private HashMap<String, List<PojoOfJsonArray>> groupDataIntoHashMap(List<PojoOfJsonArray> listOfPojosOfJsonArray) {

HashMap<String, List<PojoOfJsonArray>> groupedHashMap = new HashMap<>();

for (PojoOfJsonArray pojoOfJsonArray : listOfPojosOfJsonArray) {

String hashMapKey = pojoOfJsonArray.getDate();

if (groupedHashMap.containsKey(hashMapKey)) {
// The key is already in the HashMap; add the pojo object
// against the existing key.
groupedHashMap.get(hashMapKey).add(pojoOfJsonArray);
} else {
// The key is not there in the HashMap; create a new key-value pair
List<PojoOfJsonArray> list = new ArrayList<>();
list.add(pojoOfJsonArray);
groupedHashMap.put(hashMapKey, list);
}
}

return groupedHashMap;
}

}

the myOptions is where one would use to feed your data into.
ListItem.java

public abstract class ListItem {

public static final int TYPE_DATE = 0;
public static final int TYPE_GENERAL = 1;

abstract public int getType();
}

GeneralItem.java

public class GeneralItem extends ListItem {
private PojoOfJsonArray pojoOfJsonArray;

public PojoOfJsonArray getPojoOfJsonArray() {
return pojoOfJsonArray;
}

public void setPojoOfJsonArray(PojoOfJsonArray pojoOfJsonArray) {
this.pojoOfJsonArray = pojoOfJsonArray;
}

@Override
public int getType() {
return TYPE_GENERAL;
}

}

DateItem.java

public class DateItem extends ListItem {

private String date;

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}

@Override
public int getType() {
return TYPE_DATE;
}
}

Adapter.java this adapter is for the recyclerview if your not well informed on how to make simple sectioned recyclerview then i suggest you read on those and be good in the area because this is abit more tricky anyways:

public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private Context mContext;
List<ListItem> consolidatedList = new ArrayList<>();

public Adapter(Context context, List<ListItem> consolidatedList) {
this.consolidatedList = consolidatedList;
this.mContext = context;

}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());

switch (viewType) {

case ListItem.TYPE_GENERAL:
View v1 = inflater.inflate(R.layout.items, parent,
false);
viewHolder = new GeneralViewHolder(v1);
break;

case ListItem.TYPE_DATE:
View v2 = inflater.inflate(R.layout.itemsh, parent, false);
viewHolder = new DateViewHolder(v2);
break;
}

return viewHolder;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {

switch (viewHolder.getItemViewType()) {

case ListItem.TYPE_GENERAL:

GeneralItem generalItem = (GeneralItem) consolidatedList.get(position);
GeneralViewHolder generalViewHolder= (GeneralViewHolder) viewHolder;
generalViewHolder.txtTitle.setText(generalItem.getPojoOfJsonArray().getName());

break;

case ListItem.TYPE_DATE:
DateItem dateItem = (DateItem) consolidatedList.get(position);
DateViewHolder dateViewHolder = (DateViewHolder) viewHolder;

dateViewHolder.txtTitle.setText(dateItem.getDate());
// Populate date item data here

break;
}
}

// ViewHolder for date row item
class DateViewHolder extends RecyclerView.ViewHolder {
protected TextView txtTitle;

public DateViewHolder(View v) {
super(v);
this.txtTitle = (TextView) v.findViewById(R.id.txt);

}
}

// View holder for general row item
class GeneralViewHolder extends RecyclerView.ViewHolder {
protected TextView txtTitle;

public GeneralViewHolder(View v) {
super(v);
this.txtTitle = (TextView) v.findViewById(R.id.txt);

}
}

@Override
public int getItemViewType(int position) {
return consolidatedList.get(position).getType();
}

@Override
public int getItemCount() {
return consolidatedList != null ? consolidatedList.size() : 0;
}

}

and this has two layout being used . thus all

Divide elements on groups in RecyclerView

For example you can:

  1. Use a TreeMap<Date,List<Event>> for splitting elements by date. This will be a collection for keeping your business objects. Of course if you already have a similar structure you can keep it. It's just important to have something for easily building list of items for populating UI with right elements order.

  2. Define a dedicated abstract type for List items (e.g. ListItem) to wrap your business objects. Its implementation could be something like this:

    public abstract class ListItem {

    public static final int TYPE_HEADER = 0;
    public static final int TYPE_EVENT = 1;

    abstract public int getType();
    }
  3. Define a class for each of your List element type (here I added just two types but you can use many as you need):

    public class HeaderItem extends ListItem {

    private Date date;

    // here getters and setters
    // for title and so on, built
    // using date

    @Override
    public int getType() {
    return TYPE_HEADER;
    }

    }

    public class EventItem extends ListItem {

    private Event event;

    // here getters and setters
    // for title and so on, built
    // using event

    @Override
    public int getType() {
    return TYPE_EVENT;
    }

    }
  4. Create a List as follows (where mEventsMap is map build at point 1):

    List<ListItem> mItems;
    // ...
    mItems = new ArrayList<>();
    for (Date date : mEventsMap.keySet()) {
    HeaderItem header = new HeaderItem();
    header.setDate(date);
    mItems.add(header);
    for (Event event : mEventsMap.get(date)) {
    EventItem item = new EventItem();
    item.setEvent(event);
    mItems.add(item);
    }
    }
  5. Define an adapter for your RecyclerView, working on List defined at point 4. Here what is important is to override getItemViewType method as follows:

    @Override
    public int getItemViewType(int position) {
    return mItems.get(position).getType();
    }

    Then you need to have two layouts and ViewHolder for header and event items. Adapter methods should take care of this accordingly:

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == ListItem.TYPE_HEADER) {
    View itemView = mLayoutInflater.inflate(R.layout.view_list_item_header, parent, false);
    return new HeaderViewHolder(itemView);
    } else {
    View itemView = mLayoutInflater.inflate(R.layout.view_list_item_event, parent, false);
    return new EventViewHolder(itemView);
    }
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
    int type = getItemViewType(position);
    if (type == ListItem.TYPE_HEADER) {
    HeaderItem header = (HeaderItem) mItems.get(position);
    HeaderViewHolder holder = (HeaderViewHolder) viewHolder;
    // your logic here
    } else {
    EventItem event = (EventItem) mItems.get(position);
    EventViewHolder holder = (EventViewHolder) viewHolder;
    // your logic here
    }
    }

Here it is a repository on GitHub providing an implementation of the approach explained above.

Grouping recycler-view items by date?

Sounds like you just want to have two ViewTypes like explained here

You might also want to take a look at this library and if you want it to be expandable and sexy you could take a look at Advanced RecyclerView library.

How to add dividers, spacers, or header with text to a recylerview

I took a bit of time but I was able to do it.

This is the output

Recycler view with draggable items and group by

1) MainActivity.java

public class MainActivity extends AppCompatActivity implements OnStartDragListener{

RecyclerView recyclerView;
private ItemTouchHelper mItemTouchHelper;
private List<Item> itemList = new ArrayList<>();
private RecyclerViewAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

mAdapter = new RecyclerViewAdapter(itemList, MainActivity.this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new SeparationDecorator());
recyclerView.setAdapter(mAdapter);
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(mAdapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
prepareItemData();
}

private void prepareItemData() {
Item item = new Item("Apple Pay");
itemList.add(item);
item = new Item("1706-XXXX-XXXX-1112");
itemList.add(item);
item = new Item("Google pay");
itemList.add(item);
mAdapter.notifyDataSetChanged();
}

@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
}

2) OnStartDragListener.java

public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}

3) SimpleItemTouchHelperCallback.java

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {

private final ItemTouchHelperAdapter mAdapter;

public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}

@Override
public boolean isLongPressDragEnabled() {
return true;
}

@Override
public boolean isItemViewSwipeEnabled() {
return false; // make this true to enable swipe to delete
}

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}

}

4) ItemTouchHelperAdapter.java

public interface ItemTouchHelperAdapter {
void onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}

5) SeparationDecorator.java

public class SeparationDecorator extends RecyclerView.ItemDecoration {
private int textSize = 50;
private int groupSpacing = 100;

private Paint paint = new Paint();
{
paint.setTextSize(textSize);
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
if (position == 0) {
c.drawText("DEFAULT", view.getLeft(),
view.getTop() - groupSpacing / 2 + textSize / 3, paint);
} else if(position == 1) {
c.drawText("OTHER", view.getLeft(),
view.getTop() - groupSpacing / 2 + textSize / 3, paint);
}
}
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) == 0 || parent.getChildAdapterPosition(view) == 1) {
outRect.set(0, groupSpacing, 0, 0);
}
}
}

6) RecyclerViewAdapter.java

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> implements ItemTouchHelperAdapter{

private List<Item> itemList;
private Context context;

@Override
public void onItemMove(int fromPosition, int toPosition) {
Item prev = itemList.remove(fromPosition);
itemList.add(toPosition > fromPosition ? toPosition - 1 : toPosition, prev);
notifyItemMoved(fromPosition, toPosition);
}

@Override
public void onItemDismiss(int position) {
itemList.remove(position);
notifyItemRemoved(position);
}

public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;

public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
}
}

public RecyclerViewAdapter(List<Item> itemList, Context context) {
this.itemList = itemList;
this.context = context;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_item, parent, false);

return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Item movie = itemList.get(position);
holder.title.setText(movie.getTitle());
}

@Override
public int getItemCount() {
return itemList.size();
}
}

7) Item.java

public class Item {
private String title;

public Item(String title) {
this.title = title;
}

public void setTitle(String title) {
this.title = title;
}

public String getTitle() {
return title;
}
}

This is it. This was able to solve your problem.

I am not able to explain you the complete code, I will take some time in future definitely and explain it.

Not able to parse JSON into a recyclerview

You are getting data in an asynchronous way but you are setting data in recyclerview as a synchronous way that's why the list is empty. Follow the given strategy:

Replace adapter.notifyDataSetChanged() to update() method and remove all code after parseJSON(); method.

private void update(){ 

HashMap<String, List<StreamItem>> groupedHashMap = groupDataIntoHashMap(myOptions);

for (String date : groupedHashMap.keySet()) {
HeaderItem dateItem = new HeaderItem();
dateItem.setDate(date);
consolidatedList.add(dateItem);

for (StreamItem pojoOfJsonArray : groupedHashMap.get(date)) {
EventItem generalItem = new EventItem();
generalItem.setStreamItem(pojoOfJsonArray);//setBookingDataTabs(bookingDataTabs);
consolidatedList.add(generalItem);
}
}

adapter = new StreamArrayAdapter(this, consolidatedList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(adapter);}

How to split Recycler view into 2 divisions based on type from a JSON file in Kotlin - android studio

I ended up filtering through my json file and splitting it into 2 lists. One that contains all the card types, another for all the bank types. Then passing each through their individual recycler.

val cardData: MutableList <Data> = mutableListOf<Data>()
val bankData: MutableList <Data> = mutableListOf<Data>()

for(i in data) {
if (i.account_type.equals("card")){
cardData.add(i)
}
}

for(i in data) {
if (i.account_type.equals("bank")){
bankData.add(i)
}
}

To clarify, data is a list that uses the helper class Data using Gson, assign the json file to it in my main activity.



Related Topics



Leave a reply



Submit