I'am creating a conference application for which i get the conference event details as JSON.iam using retrofit for network calling. based on the JSON data,iam populating my recyclerview accordingly.basically it is a horizontal recyclerview inside a vertical recyclerview.what iam trying to achieve is to group all the events that fall on the same time in horizontal recyclerview and others on vertical recycler view.please help me in acheiving this.below is my code for vertical and horizontal adapters
VERTICAL ADAPTER
public class VerticalAdapter extends RecyclerView.Adapter {
private ArrayList<EventModel> mEventList;
private Context mContext;
private Map<Integer, Parcelable> scrollStatePositionsMap = new HashMap<>();
private static final String TAG = VerticalAdapter.class.getSimpleName();
private ArrayList<EventModel> tempList;
public VerticalAdapter(ArrayList<EventModel> mEventList, Context mContext) {
this.mEventList = mEventList;
this.mContext = mContext;
this.tempList = new ArrayList<>();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
VerticalItemBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.vertical_item, parent, false);
return new EventViewHolder(binding);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext);
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
((EventViewHolder) holder).mBinding.horizontalGridView.setLayoutManager(linearLayoutManager);
((EventViewHolder) holder).mBinding.horizontalGridView.setAdapter(new HorizontalAdapter(mEventList, mContext));
((EventViewHolder) holder).setPosition(position);
if (scrollStatePositionsMap.containsKey(position)) {
((EventViewHolder) holder).mBinding.horizontalGridView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
((EventViewHolder) holder).mBinding.horizontalGridView.getViewTreeObserver().removeOnPreDrawListener(this);
((EventViewHolder) holder).mBinding.horizontalGridView.getLayoutManager().onRestoreInstanceState(scrollStatePositionsMap.get(position));
return false;
}
});
}
}
@Override
public int getItemCount() {
return mEventList.size();
}
private class EventViewHolder extends RecyclerView.ViewHolder {
public int position;
private VerticalItemBinding mBinding;
public EventViewHolder(VerticalItemBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
mBinding.horizontalGridView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
scrollStatePositionsMap.put(position, recyclerView.getLayoutManager().onSaveInstanceState());
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
public void setPosition(int position) {
this.position = position;
}
}
}
HORIZONTAL ADAPTER
public class HorizontalAdapter extends RecyclerView.Adapter {
private ArrayList<EventModel> mEventList;
private Context mContext;
private static String TAG = HorizontalAdapter.class.getSimpleName();
public HorizontalAdapter(ArrayList<EventModel> mEventList, Context mContext) {
this.mEventList = mEventList;
this.mContext = mContext;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
HorizontalItemBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.horizontal_item, parent, false);
return new EventViewHolder(binding);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
StartsOn startsOn = mEventList.get(position).getStartsOn();
EndsOn endsOn = mEventList.get(position).getEndsOn();
((EventViewHolder) holder).mBinding.textTime.setText(startsOn.getDate().substring(11, 16));
((EventViewHolder) holder).mBinding.textEndtime.setText(endsOn.getDate().substring(11, 16));
((EventViewHolder) holder).mBinding.setEvents(mEventList.get(position));
}
@Override
public int getItemCount() {
return mEventList.size();
}
private class EventViewHolder extends RecyclerView.ViewHolder {
private HorizontalItemBinding mBinding;
public EventViewHolder(HorizontalItemBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
}
}
}
MY NETWORK CALL
NetworkInterface networkInterface = retrofit.create(NetworkInterface.class);
Call<ArrayList<EventModel>> call = networkInterface.getEvents(query);
Log.d(TAG, "populateFirstEvent: making call to "+query);
call.enqueue(new Callback<ArrayList<EventModel>>() {
@Override
public void onResponse(Call<ArrayList<EventModel>> call, Response<ArrayList<EventModel>> response) {
if (response.isSuccessful()) {
mBinding.verticalList.setVisibility(View.VISIBLE);
mBinding.emptyView.setVisibility(View.GONE);
mEventList.addAll(response.body());
mBinding.verticalList.setAdapter(new HorizontalAdapter(mEventList,getApplicationContext()));
mBinding.verticalList.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
}
}
@Override
public void onFailure(Call<ArrayList<EventModel>> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getLocalizedMessage());
mBinding.verticalList.setVisibility(View.GONE);
mBinding.emptyView.setVisibility(View.VISIBLE);
}
});
You could use single RecycleView and single Adapter. Use GridLayoutManager as layout manager for your RecylcerView. Take a look on its constructor
GridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout)
Take HORIZONTAL as orientation and spanCount is number of rows - "group all the events that fall on the same time". So you should sort your events. If there different events number for different rows - fill gaps with some fake empty events.
You should put RecycleView into ScrollView to make it scroll vertically.