I am using diffutil for my recycler adapters and I need many recyclerview for categorization. Should I create adapter for every recyclerview? Same view, same type data, same functions, different data btw
If you check your recycler view's onBindViewHolder method it has your holder parameter which provides you with the instance of different ViewHolders you have and accordingly set the layout for the recycler view.
For example, in my case I had to use a single recyclerView adapter to create an instance Income as well as expense in a list.
This is how my onBindViewHolder looks:
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
DialogDetails d=new DialogDetails();
if (holder instanceof IncomeListHolder){
((IncomeListHolder)holder).categoryText.setText(expensesList.get(position).getCategory());
((IncomeListHolder)holder).incomeText.setText("+"+expensesList.get(position).getAmount());
((IncomeListHolder)holder).incomeText.setTextColor(context.getResources().getColor(R.color.income_color));
}
if (holder instanceof ExpensesListHolder){
((ExpensesListHolder) holder).category.setText(list.get(position-expensesList.size()).getCategory());
((ExpensesListHolder) holder).expenseText.setText("-"+list.get(position- expensesList.size()).getExpense());
((ExpensesListHolder) holder).expenseText.setTextColor(context.getResources().getColor(R.color.expense_color));
}
//.setText(String.valueOf(balanceList.get(position).getIncome()));
}
You also have to create separate viewHolders for all the list data you wish to display,like:
public class IncomeListHolder extends RecyclerView.ViewHolder {
TextView categoryText;
TextView incomeText;
public IncomeListHolder(#NonNull View itemView) {
super(itemView);
categoryText=itemView.findViewById(R.id.main_category_text_view);
incomeText=itemView.findViewById(R.id.expenses_text_view);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position=getAdapterPosition();
if (listener!=null && position!=RecyclerView.NO_POSITION){
listener.getIncomeData(expensesList.get(position),view);
details.setUpdate(true);
}
}
});
}
}
public class ExpensesListHolder extends RecyclerView.ViewHolder{
TextView category;
TextView expenseText;
public ExpensesListHolder(#NonNull View itemView) {
super(itemView);
category=itemView.findViewById(R.id.main_category_text_view_2);
expenseText=itemView.findViewById(R.id.expenses_text_view_2);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position=getAdapterPosition();
if (listener!=null && position!=RecyclerView.NO_POSITION){
listener.getExpenseData(list.get(position-expensesList.size()),view);
details.setUpdate(true);
}
}
});
}
}
My whole recycler view adapter:
public class IncomeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
final int VIEW_TYPE_INCOME=0;
final int VIEW_TYPE_EXPENSE=1;
View view;
List<DataBaseEntity> expensesList=new ArrayList<>();
List<ExpenseDataEntity> list=new ArrayList<>();
Context context;
OnItemClickListener listener;
DialogDetails details=new DialogDetails();
public IncomeListAdapter(Context context) {
this.context = context;
}
//
// View v=LayoutInflater.from(context).inflate(R.layout.fragment_expense_home,null);
//// t=v.findViewById(R.id.income_text_view);
// }
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType==VIEW_TYPE_INCOME) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.expenses_list, parent, false);
return new IncomeListHolder(view);
}
if (viewType==VIEW_TYPE_EXPENSE){
view=LayoutInflater.from(parent.getContext()).inflate(R.layout.expense_layout_list,parent,false);
return new ExpensesListHolder(view);
}
return null;
}
public interface OnItemClickListener{
void getIncomeData(DataBaseEntity dataBaseEntity,View view);
void getExpenseData(ExpenseDataEntity expenseDataEntity,View view);
}
public void setOnItemClickListener(OnItemClickListener listener){
this.listener=listener;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
DialogDetails d=new DialogDetails();
if (holder instanceof IncomeListHolder){
((IncomeListHolder)holder).categoryText.setText(expensesList.get(position).getCategory());
((IncomeListHolder)holder).incomeText.setText("+"+expensesList.get(position).getAmount());
((IncomeListHolder)holder).incomeText.setTextColor(context.getResources().getColor(R.color.income_color));
}
if (holder instanceof ExpensesListHolder){
((ExpensesListHolder) holder).category.setText(list.get(position-expensesList.size()).getCategory());
((ExpensesListHolder) holder).expenseText.setText("-"+list.get(position- expensesList.size()).getExpense());
((ExpensesListHolder) holder).expenseText.setTextColor(context.getResources().getColor(R.color.expense_color));
}
//.setText(String.valueOf(balanceList.get(position).getIncome()));
}
public DataBaseEntity getDataAt(int position){
return expensesList.get(position);
}
public ExpenseDataEntity getExpenseAt(int position){
return list.get(position- expensesList.size());
}
#Override
public int getItemCount() {
return expensesList.size()+list.size();
}
#Override
public int getItemViewType(int position) {
if (position< expensesList.size()){
return VIEW_TYPE_INCOME;
}
if (position-expensesList.size()< list.size()){
return VIEW_TYPE_EXPENSE;
}
return -1;
}
public void setExpensesList(List<DataBaseEntity> expensesList){
this.expensesList=expensesList;
notifyDataSetChanged();
}
public void setList(List<ExpenseDataEntity> list){
this.list=list;
notifyDataSetChanged();
}
// public void setBalanceList(List<BalanceSheetEntity> balanceList){
// this.balanceList=balanceList;
// notifyDataSetChanged();
// }
public class IncomeListHolder extends RecyclerView.ViewHolder {
TextView categoryText;
TextView incomeText;
public IncomeListHolder(#NonNull View itemView) {
super(itemView);
categoryText=itemView.findViewById(R.id.main_category_text_view);
incomeText=itemView.findViewById(R.id.expenses_text_view);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position=getAdapterPosition();
if (listener!=null && position!=RecyclerView.NO_POSITION){
listener.getIncomeData(expensesList.get(position),view);
details.setUpdate(true);
}
}
});
}
}
public class ExpensesListHolder extends RecyclerView.ViewHolder{
TextView category;
TextView expenseText;
public ExpensesListHolder(#NonNull View itemView) {
super(itemView);
category=itemView.findViewById(R.id.main_category_text_view_2);
expenseText=itemView.findViewById(R.id.expenses_text_view_2);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position=getAdapterPosition();
if (listener!=null && position!=RecyclerView.NO_POSITION){
listener.getExpenseData(list.get(position-expensesList.size()),view);
details.setUpdate(true);
}
}
});
}
}
}
Related
I am using RecyclerView in BottomSheet.The data is fetched successfuly but unable to get click action on the RecyclerView items. This is my BottomSheetAdapter code :
public class BottomSheetAdapter extends RecyclerView.Adapter<BottomSheetAdapter.ViewHolder> {
List<UserDetailsModel> userDetailsModelList;
Context context;
private Onitemclicklistenersuggestion listener;
public BottomSheetAdapter(List<UserDetailsModel> userDetailsModelList, Context context) {
this.userDetailsModelList = userDetailsModelList;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_recycler_items, parent, false);
return new BottomSheetAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
UserDetailsModel model = userDetailsModelList.get(position);
holder.firstNameLabel.setText(model.getFirst_name().trim());
}
#Override
public int getItemCount() {
return userDetailsModelList.size();
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView firstNameLabel;
public ViewHolder(#NonNull View itemView) {
super(itemView);
firstNameLabel = itemView.findViewById(R.id.firstNameLabel);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.clicktoupdate(position);
}
}
}
}
public interface Onitemclicklistenersuggestion {
void clicktoupdate(int poistion);
}
public void setOnitemclicklistener(Onitemclicklistenersuggestion mlistener) {
listener = mlistener;
}
}
This is my BottomSheetDialog code :
public class BottomSheetDialog extends BottomSheetDialogFragment
implements BottomSheetAdapter.Onitemclicklistenersuggestion {
bottomSheetAdapter = new BottomSheetAdapter(userDetailsModelList, getActivity());
bottomSheetRecycler.setAdapter(bottomSheetAdapter);
bottomSheetRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
bottomSheetAdapter.setOnitemclicklistener(new BottomSheetAdapter.Onitemclicklistenersuggestion() {
#Override
public void clicktoupdate(int poistion) {
Log.e("Pos", "Pos");
}
});
bottomSheetAdapter.notifyDataSetChanged();
}
#Override
public void clicktoupdate(int poistion) {
Toast.makeText(getContext(), ""+poistion, Toast.LENGTH_SHORT).show();
}
But after clicking the RecyclerView items neither the Log or the Toast message shows up. Please help me fix it. Thanks in Millions.
Try setting the onClick logic inside your ViewHolder class.
So something like,
class ViewHolder extends RecyclerView.ViewHolder {
TextView firstNameLabel;
public ViewHolder(#NonNull View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// show a toast msg or whatever action you need...
}
});
firstNameLabel = itemView.findViewById(R.id.firstNameLabel);
}
}
I am using RecyclerView and I want to view the the data of list item that I click on. I'm using itemView.getTag() to get the value of index and typecasting it to my CustomAdapter.
I tried various ways but not to help. please help me.
Here's my code:
public class DonorAdapter extends RecyclerView.Adapter<DonorAdapter.ViewHolder> {
ArrayList<Donor> donorsList;
ItemSelected activity;
public interface ItemSelected{
void onItemClicked(int index);
}
public DonorAdapter(Context context, ArrayList<Donor> list){
activity = (ItemSelected) context;
donorsList = list;
}
public class ViewHolder extends RecyclerView.ViewHolder
{
ImageView ivDonorGender;
TextView tvListName;
TextView tvBloodGroup;
public ViewHolder(#NonNull final View itemView) {
super(itemView);
ivDonorGender = itemView.findViewById(R.id.ivDonorGender);
tvListName = itemView.findViewById(R.id.tvListName);
tvBloodGroup = itemView.findViewById(R.id.tvListBloodGroup);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
activity.onItemClicked(donorsList.indexOf((Donor) itemView.getTag()));
}
});
}
}
#NonNull
#Override
public DonorAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.donors_list, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull DonorAdapter.ViewHolder holder, int position) {
holder.tvListName.setText(donorsList.get(position).getName());
holder.tvBloodGroup.setText(donorsList.get(position).getSurname());
}
}
#Override
public int getItemCount() {
return donorsList.size();
}
}
I am new to android so pardon me if I can't explain properly
Here's the problematic part
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
activity.onItemClicked(donorsList.indexOf((Donor)
itemView.getTag()));
}
I think you need to set the tag for each recycled item in onBindViewHolder
#Override
public void onBindViewHolder(#NonNull DonorAdapter.ViewHolder holder, int position) {
holder.tvListName.setText(donorsList.get(position).getName());
holder.tvBloodGroup.setText(donorsList.get(position).getSurname());
holder.itemView.setTag(donorsList.get(position)); // change here
}
}
In activity
borderFav = (Button) findViewById(R.id.borderFav);
fav = (Button) findViewById(R.id.fav);
borderFav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
borderFav.setVisibility(View.GONE);
fav.setVisibility(View.VISIBLE);
}
});
fav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
fav.setVisibility(View.GONE);
borderFav.setVisibility(View.VISIBLE);
}
});
In XML of a RecyclerView item
<Button
android:id="#+id/borderFav"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="10"
android:layout_gravity="center"
android:background="#drawable/favorite_border_24"
android:visibility="visible"
/>
<Button
android:id="#+id/fav"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="10"
android:layout_gravity="center"
android:background="#drawable/favorite_24"
android:visibility="gone"
/>
Logic is simple, empty heart gets clicked, turns into full heart, full heart clicked turns into empty heart, but Logcat gives a NullPointer in the activity.
If I remove the onClickListeners for those two, there is no error.
RecyclerView Adapter code
public class AllAdapter extends RecyclerView.Adapter<AllAdapter.ViewHolder> {
private ArrayList<Food> data;
private OnItemListener onItemListener;
public ArrayList<Food> getData() {
return data;
}
public AllAdapter(ArrayList<Food> data, OnItemListener onItemListener) {
this.data = data;
this.onItemListener = onItemListener;
}
#NonNull
#Override
public AllAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(v, onItemListener);
}
#Override
public void onBindViewHolder(#NonNull AllAdapter.ViewHolder holder, final int position) {
holder.textView.setText(this.data.get(position).getName());
}
#Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView textView;
private OnItemListener onItemListener;
public ViewHolder(#NonNull View itemView, OnItemListener onItemListener) {
super(itemView);
this.textView = itemView.findViewById(R.id.tv);
this.onItemListener = onItemListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
onItemListener.onClick(getAdapterPosition());
}
}
public void filterList(ArrayList<Food> filteredList){
data = filteredList;
notifyDataSetChanged();
}
public interface OnItemListener{
void onClick(int position);
}
}
I did not touch the Adapter to implement the favourite button.
Change your adapter to this and see if it works,
public class AllAdapter extends RecyclerView.Adapter<AllAdapter.ViewHolder> {
private ArrayList<Food> data;
private OnItemListener onItemListener;
public ArrayList<Food> getData() {
return data;
}
public AllAdapter(ArrayList<Food> data, OnItemListener onItemListener) {
this.data = data;
this.onItemListener = onItemListener;
}
#NonNull
#Override
public AllAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(v, onItemListener);
}
#Override
public void onBindViewHolder(#NonNull AllAdapter.ViewHolder holder, final int position) {
holder.textView.setText(this.data.get(position).getName());
holder.borderFav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.borderFav.setVisibility(View.GONE);
holder.fav.setVisibility(View.VISIBLE);
}
});
holder.fav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.fav.setVisibility(View.GONE);
holder.borderFav.setVisibility(View.VISIBLE);
}
});
}
#Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView textView;
private Button borderFav, fav;
private OnItemListener onItemListener;
public ViewHolder(#NonNull View itemView, OnItemListener onItemListener) {
super(itemView);
textView = itemView.findViewById(R.id.tv);
borderFav = itemView.findViewById(R.id.borderFav);
fav = itemView.findViewById(R.id.fav);
this.onItemListener = onItemListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
onItemListener.onClick(getAdapterPosition());
}
}
public void filterList(ArrayList<Food> filteredList) {
data = filteredList;
notifyDataSetChanged();
}
public interface OnItemListener {
void onClick(int position);
}
}
From the code you have pasted it seems, you are doing it wrong, the xml items of recyclerview belongs to the recyclerview adapter so you should place those click listeners in your onBindViewHolder() rather than inside activity.
I want to do different job for different RecycleView item. I created custom OnClickListener for RecycleView and using this from my activity. But problem is when I want to get RecycleView Item Id form OnClick it's return -1. I can't able to check view Id.
RecycleView Adapter:
public class AddFoodAdapter extends RecyclerView.Adapter<AddFoodAdapter.AddFoodApapterVH>{
private ArrayList<FoodReviewItem> foodList = new ArrayList<>();
OnItemClickListener onItemClickListener;
public AddFoodAdapter(){
}
#Override
public AddFoodApapterVH onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycleview_add_food_item, parent, false);
return new AddFoodApapterVH(itemView);
}
#Override
public void onBindViewHolder(AddFoodApapterVH holder, int position) {
holder.tvFoodTitle.setText(foodList.get(position).getFoodName());
holder.tvFoodPrice.setText(foodList.get(position).getFoodPrice());
}
public void add(int position,FoodReviewItem foodItem){
foodList.add(position,foodItem);
notifyItemInserted(position);
}
public void delete(int position){
foodList.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
return foodList.size();
}
public class AddFoodApapterVH extends RecyclerView.ViewHolder implements View.OnClickListener{
public ImageView ivEditFoodItem;
public TextView tvFoodTitle;
public RatingBar rbFoodRating;
public ImageView ivDeleteFoodItem;
public TextView tvFoodPrice;
public AddFoodApapterVH(View itemView) {
super(itemView);
ivEditFoodItem = (ImageView) itemView.findViewById(R.id.ivEditFoodItem);
tvFoodTitle = (TextView) itemView.findViewById(R.id.tvAddFoodItemTitle);
rbFoodRating = (RatingBar) itemView.findViewById(R.id.rbAddFoodItemRating);
ivDeleteFoodItem = (ImageView) itemView.findViewById(R.id.ivDeleteFoodItem);
tvFoodPrice = (TextView) itemView.findViewById(R.id.tvAddFoodItemPrice);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(onItemClickListener!=null){
onItemClickListener.onItemClick(v, getAdapterPosition());
}
}
}
public interface OnItemClickListener {
public void onItemClick(View view , int position);
}
public void SetOnItemClickListener(final OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
}
Form Activity:
private void setUpFoodItemApapter() {
foodItemRecyclerView = (RecyclerView) findViewById(R.id.rvFoodItems);
addFoodAdapter = new AddFoodAdapter();
final LinearLayoutManager layoutManager = new org.solovyev.android.views.llm.LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
foodItemRecyclerView.setLayoutManager(layoutManager);
foodItemRecyclerView.addItemDecoration(new DividerItemDecoration(this, null));
foodItemRecyclerView.setAdapter(addFoodAdapter);
addFoodAdapter.SetOnItemClickListener(new AddFoodAdapter.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Log.i("getid",""+view.getId()); //return -1
Log.i("getid",""+R.id.ivDeleteFoodItem); //return id
// not working
if(view.getId() == R.id.ivDeleteFoodItem){
addFoodAdapter.delete(position);
}
}
});
}
addFoodAdapter.SetOnItemClickListener(new AddFoodAdapter.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
ImageView iv = (ImageView)view;// get imageView
int id = iv.getId();
if(id == R.id.ivDeleteFoodItem){
addFoodAdapter.delete(position);
}
}
});
I am having trouble removing items from RecyclerView. When I click on delete, the item is removed from RecyclerView, but comes back when I open the app again. I'm hoping it is just a minor issue that someone here can point out or direct me to what area to troubleshoot. The removeItem(String item) in bold is what I think is the issue. You can't see it in this post, but it is "not used".
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
private List<Grocery> mListData;
private SQLGroceryHelper helper;
RecyclerViewAdapter adapter;
//Adapter's Constructor//
public RecyclerViewAdapter(List<Grocery> mDataList) {
this.mListData = mDataList;
}
//Provide a reference to the views for each contact item//
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView rowItem;
ImageButton purchasedButton;
ImageButton deleteButton;
LinearLayout linearLayout;
public MyViewHolder(View itemView) {
super(itemView);
linearLayout = (LinearLayout) itemView.findViewById(R.id.recycler_row);
rowItem = (TextView) itemView.findViewById(R.id.item_field1);
purchasedButton = (ImageButton) itemView.findViewById(R.id.item_purchased);
deleteButton = (ImageButton) itemView.findViewById(R.id.delete_item);
}
}
//Inflate the view based on the viewtype provided//
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//Create a new view by inflating the row item xml//
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false);
//Set the view to the ViewHolder//
MyViewHolder holder = new MyViewHolder(row);
return holder;
}
//Display data at the specified position//
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.rowItem.setText(mListData.get(position).getTextItem());
holder.purchasedButton.setOnClickListener(new View.OnClickListener() {
//Ignore this click for now//
#Override
public void onClick(View v) {
removeItem(position);
}
});
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
removeItem(position);
}
});
}
public void **removeItem**(String item) {
int position = mListData.indexOf(item);
if (position != -1) {
mListData.remove(item);
notifyItemRemoved(position);
}
}
public void removeItem(int position) {
mListData.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
if (mListData == null) {
return 0;
}
return mListData.size();
}
}
You are removing the data from local object, mListData I guess the original data object remains intact. Remove the data item from the original data object as well
Declare a interface
public interface AdapterCommunication{
void removeStringItem(int position);
}
then in your adapter
private AdapterCommunication mListener;
public void setOnClickListener(AdapterCommunication listener){
mListener = listener;
}
Then from your activity where you initialize the adapter
RecyclerViewAdapter adapter = new RecyclerViewAdapter(list);
adapter.setOnClickListener(new AdapterCommunication{
public void removeStringItem(int position){
list.remove(position);
adapter.notifyDataSetChanged();
}
});
In your adaper,
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.remove(position);
}
});