I have a recyclerview. It loads when it scrolls. But when I scroll it from top to bottom continuously, it crashes (or closes) after a while .
Error :
Cannot scroll to position a LayoutManager set. Call setLayoutManager with a non-null argument.
E: No adapter attached; skipping layout
A: art/runtime/indirect_reference_table.cc:76] Check failed: table_mem_map_.get() != nullptr ashmem_create_region failed for 'indirect ref table': Too many open files
E: Cannot scroll to position a LayoutManager set. Call setLayoutManager with a non-null argument.
A: art/runtime/indirect_reference_table.cc:76] Check failed: table_mem_map_.get() != nullptr ashmem_create_region failed for 'indirect ref table': Too many open files
BookSearchResultListAdapter.java
public class BookSearchResultListAdapter extends RecyclerView.Adapter<BookSearchResultListAdapter.ViewHolder> implements View.OnClickListener{
private ArrayList<ProductModel> productList;
private Fragment fragment;
private RecyclerView recyclerView;
private int position = 0;
public BookSearchResultListAdapter(Fragment fragment, ArrayList<ProductModel> productList, RecyclerView recyclerView) {
this.productList = productList;
this.fragment = fragment;
this.recyclerView = recyclerView;
}
#Override
public void onClick(View v) {
int position = recyclerView.getChildLayoutPosition(v);
((BookSearchResultAdapterListener)fragment).onProductItemClicked(productList.get(position));
}
private void setOnScrollListener() {
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(recyclerView.getLayoutManager() != null){
LinearLayoutManager lm= (LinearLayoutManager) recyclerView.getLayoutManager();
int Lastposition = lm.findLastCompletelyVisibleItemPosition();
if(Lastposition == productList.size()-1 && Lastposition != position){
position = lm.findLastCompletelyVisibleItemPosition();
((BookSearchResultAdapterListener)fragment).onListScrolled();
}
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
public void addCollectionToList(ArrayList<ProductModel> productList){
this.productList.addAll(productList);
notifyItemRangeChanged(0, productList.size() - 1);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView productName;
public TextView manufacturerName;
public TextView publisherName;
public ImageView image;
public ImageView isShelvedIcon;
public ViewHolder(View view) {
super(view);
}
}
#Override
public BookSearchResultListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.component_library_product, parent, false);
ViewHolder holder = new ViewHolder(v);
holder.productName = (TextView) v.findViewById(R.id.productName);
holder.manufacturerName = (TextView)v.findViewById(R.id.pageNumber);
holder.publisherName = (TextView)v.findViewById(R.id.publisherName);
holder.image = (ImageView)v.findViewById(R.id.productImage);
holder.isShelvedIcon = (ImageView)v.findViewById(R.id.isShelvedIcon);
holder.productName.setTypeface(App.MUSEO_300);
holder.manufacturerName.setTypeface(App.MUSEO_300);
holder.publisherName.setTypeface(App.MUSEO_300);
holder.isShelvedIcon.setVisibility(View.GONE);
v.setOnClickListener(this);
setOnScrollListener();
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final ProductModel productModel = productList.get(position);
holder.productName.setText(productModel.getName());
holder.manufacturerName.setText(productModel.getManufacturer());
holder.publisherName.setText(productModel.getPublisher());
Picasso.Builder builder = new Picasso.Builder(fragment.getContext());
Picasso picasso = builder.build();
picasso.with(fragment.getContext()).load(productModel.getImage()).into(holder.image);
}
#Override
public int getItemCount() {
return productList.size();
}
public interface BookSearchResultAdapterListener {
void onProductItemClicked(ProductModel productModel);
void onListScrolled();
}
}
I found solution.It is related with Picasso library. Just change the code below :
Picasso.Builder builder = new Picasso.Builder(fragment.getContext());
Picasso picasso = builder.build();
picasso.with(fragment.getContext()).load(productModel.getImage()).into(holder.image);
to :
Picasso.with(fragment.getContext()).load(productModel.getImage()).into(holder.image);
Related
I am using nestedRecyclerView with Vertical parent recyclerview and horizontal child views. I have list of 10 items and each item contains a list for child recyclerview.
When I run the app, parent adapter's onbindviewholder getting called 10 items which is the total size of the parent list. I want to know why it is happening. It should call 4 or 5 onbindviewholder depending on the screen size but it is calling for all items which is unintended.
Parent Recyclerview initialization
homeRecyclerViewAdapter = new HomeRecyclerViewAdapter(getContext(), MR, (AppCompatActivity) getActivity());
homeRecyclerViewAdapter.setDataList(homeArrayList);
LinearLayoutManager mLinearLayoutManager3 = new LinearLayoutManager(getContext());
mLinearLayoutManager3.setOrientation(CustomLinearLayoutManager.VERTICAL);
homeRecyclerView.setLayoutManager(mLinearLayoutManager3);
homeRecyclerView.setAdapter(homeRecyclerViewAdapter);
Parent Adapter -
public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List dataList;
private Context mContext;
Typeface MR;
static String PACKAGE_NAME;
Utils utils;
CustomClickEvents customClickEvents;
AppCompatActivity appCompatActivity;
public HomeRecyclerViewAdapter(Context mContext, Typeface MR, int type, CustomClickEvents customClickEvents) {
this.mContext = mContext;
this.MR = MR;
this.customClickEvents = customClickEvents;
utils = new Utils();
}
RecyclerView.RecycledViewPool pool;
public HomeRecyclerViewAdapter(Context mContext, Typeface MR, AppCompatActivity appCompatActivity) {
pool = new RecyclerView.RecycledViewPool();
this.mContext = mContext;
this.MR = MR;
this.appCompatActivity = appCompatActivity;
utils = new Utils();
}
public void setDataList(List upiAppsList) {
this.dataList = upiAppsList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
PACKAGE_NAME = mContext.getPackageName();
if (viewType == Constants.HomePageViewTypes.TYPE_0) {
view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_layout, null);
return new RecyclerViewHolder(view);
} else if (viewType == Constants.HomePageViewTypes.TYPE_1) {
view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_layout, null);
return new RecyclerViewHolder(view);
} else if (viewType == Constants.HomePageViewTypes.TYPE_2) {
view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_layout, null);
return new RecyclerViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder itemViewHolder, int position) {
Log.d("recyclerview", "HomeRecyclerViewHolder onbindviewholder + pos" + position);
Log.d("recyclerview", "HomeRecyclerViewHolder dataList.get(position):" + dataList.get(position));
RecyclerViewHolder holder = (RecyclerViewHolder) itemViewHolder;
holder.commonRecyclerViewAdapter.setDataList(((HomePageViewModel) dataList.get(position)).getDataList());
}
public void setbackgroundcolortoitem(int position, RecyclerViewHolder viewHolder, boolean is_checked) {
int modulus_position = position % 4;
Log.d("tag", "position ---- > " + modulus_position);
}
class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
RecyclerView mRecyclerView;
CommonRecyclerViewAdapter commonRecyclerViewAdapter;
public RecyclerViewHolder(View itemView) {
super(itemView);
mRecyclerView = itemView.findViewById(R.id.mrecyclerview);
mRecyclerView.setPadding((int) (8 * utils.getScreenDensity(mContext)), 0, 0, (int) (8 * utils.getScreenDensity(mContext)));
// mRecyclerView.requestDisallowInterceptTouchEvent(false);
commonRecyclerViewAdapter = new CommonRecyclerViewAdapter(mContext, MR, 6, appCompatActivity);
LinearLayoutManager mLinearLayoutManager3 = new LinearLayoutManager(appCompatActivity, LinearLayoutManager.HORIZONTAL, false) {
#Override
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
// force height of viewHolder here, this will override layout_height from xml
Log.d("upisdk", "HomeRecyclerView getwidth:" + getWidth());
lp.width = (int) (getWidth() / 1.6);
return true;
}
};
mLinearLayoutManager3.setOrientation(CustomLinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(mLinearLayoutManager3);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(commonRecyclerViewAdapter);
}
#Override
public void onClick(View v) {
int position = getLayoutPosition();
switch (v.getId()) {
case R.id.mainlayout:
break;
}
}
}
#Override
public int getItemCount() {
return dataList.size();
}
#Override
public int getItemViewType(int position) {
if (dataList.get(position) instanceof HomePageViewModel) {
if (((HomePageViewModel) dataList.get(position)).getLayoutType() == Constants.HomePageViewTypes.TYPE_0) {
return Constants.HomePageViewTypes.TYPE_0;
}
}
return -1;
}
}
I want parent onbindviewholder to get called for the items displaying currently on screen which is the supposed behaviour of RecyclerView.
Is the parent View of the Parent RecycleView a ScrollView or NestedScrollView, bro? If true, please remove it
I have a recycler view that shows transaction information. everything works good when its loaded but after scrolling a bit, contents of different rows gets mixed up.
Here is my code:
public TransactionAdapter.VHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.cell_transaction_history,parent,false);
VHolder holder = new VHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull TransactionAdapter.VHolder holder, int position) {
final Transaction transaction = transactionList.get(position);
holder.setData(transaction);
}
#Override
public int getItemCount() {
return transactionList.size();
}
private void setTransactionList(ArrayList<Transaction> transactions) {
this.transactionList = transactions;
}
And the ViewHolder:
private class VHolder extends RecyclerView.ViewHolder {
private AppCompatTextView schemeName;
private AppCompatTextView amount;
private AppCompatTextView bank;
private AppCompatTextView date;
private AppCompatTextView status;
VHolder(View itemView) {
super(itemView);
schemeName = itemView.findViewById(R.id.scheme_name);
amount = itemView.findViewById(R.id.amount);
bank = itemView.findViewById(R.id.bank);
date = itemView.findViewById(R.id.transaction_date);
status = itemView.findViewById(R.id.transaction_status);
}
private void setData(Transaction transaction) {
schemeName.setText(transaction.getSchemeName());
bank.setText(transaction.getBankName());
date.setText(transaction.getTranDate());
int amountValue = Integer.parseInt(transaction.getAmount());
if(amountValue < 0)
amount.setTextColor(getResources().getColor(R.color.color_status_cancelled));
else
amount.setTextColor(getResources().getColor(R.color.color_status_active));
amount.setText(abs(amountValue));
Drawable drawable = status.getCompoundDrawablesRelative()[0];
String st = transaction.getOrderStatus();
if(st.equalsIgnoreCase(TRAN_STATUS_PROCESSED)){
drawable.setTint(getResources().getColor(R.color.color_status_active));
status.setText(TRAN_STATUS_PROCESSED);
} else {
drawable.setTint(getResources().getColor(R.color.color_status_cancelled));
status.setText(TRAN_STATUS_REJECTED);
}
}
}
Tried setting
holder.setIsRecyclable(false);
but that is not an ideal solution I believe.
UPDATE:
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
setContent(getUserTransactions());
And setContent() method:
private void setContent(ArrayList<Transaction> transactions) {
if(adapter == null) {
adapter = new TransactionAdapter(getLayoutInflater(),transactions);
recyclerView.setAdapter(adapter);
} else {
adapter.setTransactionList(transactions);
}
adapter.notifyDataSetChanged();
}
I'm trying to build a simple activity for messaging in android.
I have a RecyclerView that list the messages and I set a ScrollListener on it.
When the firstVisibleItem is the third of the list (RecyclerView stack from end), I will make a call to load other elements.
I add this element to my array and I set a new adapter on my RecyclerView for the update.
When I set the new adapter, the list starts one more time from the last message.
So far I have tried to use scrollToPosition to go to the message where the user was before scrollListener was triggered, but still not work at all because the lastVisibleItem become 1 every time.
Is there a way to maintain the last firstVisible element and set this element as the top element after reset the Adapter?
This is the onCreateMethod.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
lastOffset = 0;
requestSize = 20;
loadMessage()
mAdapter = new ChatAdapter(this,mess);
llm = new LinearLayoutManager(this);
llm.setStackFromEnd(true);
mex_list.setLayoutManager(llm);
mex_list.setAdapter(mAdapter);
mex_list.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int lastVisible = llm.findLastVisibleItemPosition();
int firstVisible = llm.findFirstVisibleItemPosition();
lastFirstVisibleItem = firstVisibleItem; //lastFirstVisibleItem is a global variable
if(firstVisible <= 3){
if(!loading) {
loading = true;
loadMessage();
}
}
Log.d("Test Scroll", "LAST: "+ lastVisible+" FIRST: "+firstVisible);
}
});}
This is where the laodMessage() result was managed.
public void manageResult(Object pr, int caller) {
if(caller == MESSAGES_REQ){
if(mess == null)
mess = new ArrayList<>();
ArrayList<Message> tail = (ArrayList<Message>) pr;
if(tail != null && tail.size() > 0) {
lastOffset += tail.size();
mess.addAll(tail);
mAdapter = new ChatAdapter(ctx, mess);
mex_list.setAdapter(mAdapter);
}
llm.scrollToPosition(lastFirstVisibleItem);//lastFirstVisibleItem became always 1
spinner.setVisibility(View.GONE);
printEmpMex(View.GONE);
mex_list.setVisibility(View.VISIBLE);
loading = false;
}
}
This is the ChatAdapter.
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> {
private ArrayList<Message> listOfMessages;
private static Context ctx;
private static final int SENT = 100;
private static final int RECIVED = 200;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView text;
public TextView hour;
public ViewHolder(View v) {
super(v);
text = (TextView) v.findViewById(R.id.text_body);
hour = (TextView) v.findViewById(R.id.time);
}
void bind(Message m){
text.setText(m.getBody());
hour.setText(formatDateAndHour(m.getDate()));
}
}
public ChatAdapter(Context ctx, ArrayList<Message> m) {
listOfMessages = m;
this.ctx = ctx;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view;
if (viewType == SENT) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_mex_sent, parent, false);
return new ViewHolder(view);
}
else if (viewType == RECIVED){
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_mex_recived, parent, false);
return new ViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message mex = listOfMessages.get(position);
holder.bind(mex);
}
#Override
public int getItemCount() {
return listOfMessages.size();
}
#Override
public int getItemViewType(int position) {
Message m = listOfMessages.get(position);
if(m.getSender().getIdUser().equals(loggedUser.getIdUser()))
return SENT;
else
return RECIVED;
}}
I really don't know how to make it work.
Every approach is welcome.
Thanks in advance.
I have RecyclerView and I am inflating data. My requirement is that I have to show first item text in black color, the rest of the items should be in grey. And when user scroll then that grey color item should be black and its follower would be in grey again. I was thinking to this using position but I am confused.
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>
implements RecyclerViewFastScroller.BubbleTextGetter {
private List<String> mDataArray;
public RecyclerViewAdapter(List<String> dataset) {
mDataArray = dataset;
}
#Override
public int getItemCount() {
if (mDataArray == null)
return 0;
return mDataArray.size();
}
#Override
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_view_layout, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataArray.get(position));
}
#Override
public String getTextToShowInBubble(int pos) {
if (pos < 0 || pos >= mDataArray.size())
return null;
String name = mDataArray.get(pos);
if (name == null || name.length() < 1)
return null;
return mDataArray.get(pos).substring(0, 1);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.tv_alphabet)
public TextView mTextView;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
My updated code for onScrollIng and dynamic changing
#Override
public void onBindViewHolder(MessageAdapter.ViewHolder holder, int position) {
/*Tuesday, April 10, 2001 3:51 PM*/
msgModels = msgList.get(position);
if (msgList.get(position) != null) {
holder.msgTitle.setText(msgModels.getMessageTitle());
holder.msgDescription.setText(msgModels.getMessageDescription());
holder.msgDate.setText(msgModels.getMessageDate());
}
if (position == firstVisible) {
holder.msgTitle.setTextColor(Color.RED);
holder.msgDescription.setTextColor(Color.RED);
holder.msgDate.setTextColor(Color.RED);
}else{
holder.msgTitle.setTextColor(Color.BLUE);
holder.msgDescription.setTextColor(Color.BLUE);
holder.msgDate.setTextColor(Color.BLUE);
}
}
#Override
public int getItemCount() {
return msgList.size();
}
private int firstVisible = 0;
public void changeItem(int position){
firstVisible = position;
notifyItemChanged(firstVisible);
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView msgTitle, msgDescription,msgDate;
public ViewHolder(View view) {
super(view);
msgTitle = (TextView)view.findViewById(R.id.msgTitle);
msgDescription = (TextView)view.findViewById(R.id.msgDescription);
msgDate = (TextView)view.findViewById(R.id.msgDate);
}
}
}
My Activity where I am calling Recycler onScroll
private ProgressDialog mProgressDialog = null;
private static final String API_MSG_CALL = "API_MSG_CALL";
private Map<String, String> mapobject;
private LinearLayoutManager linearLayoutManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_message, null);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_viewLaws);
mRecyclerView.setAdapter(msgAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
msgAdapter = new MessageAdapter(msgList, getActivity(), this);
linearLayoutManager = new LinearLayoutManager(getActivity());
//msgAdapter.notifyDataSetChanged();
mProgressDialog = new ProgressDialog(getActivity());
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int firstVisible = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
msgAdapter.changeItem(firstVisible);
}
});
use holder.itemView.setBackgroundColor(...);
Example
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemView.setBackgroundColor(yourcolor);
holder.mTextView.setText(mDataArray.get(position));
}
Update:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
if(position==0){
holder.itemView.setBackgroundColor(Color.BLACK);
}else{
holder.itemView.setBackgroundColor(Color.GREY);
}
holder.mTextView.setText(mDataArray.get(position));
}
first in your main Activity use this code to find the first visible item:
recyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int firstVisible = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
RecyclerViewAdapter.changeItem(firstVisible);
}
});
then in your Adapter add this method:
private int firstVisible = 0;
public void changeItem(int position){
firstVisible = position;
notifyItemChanged(firstVisible);
notifyDataSetChanged();
}
and in onBindViewHolder add this code:
if (position == firstVisible) {
holder.txtNumber.setBackgroundColor(mContext.getResources().getColor(R.color.black));
}
I just use a text as an example but you can change the cardview's background too
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.