I have a fragment that displays a RecyclerView
. I am currently handling the onclick
event in my holder class like this:
public class CategoryHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ImageView categoryImageView;
public TextView categoryNameTextView;
public TextView categoryAmountTextView;
ArrayList<Category> categoriesArrayList = new ArrayList<>();
Context context;
public CategoryHolder(View itemView, Context context, ArrayList<Category> categories) {
super(itemView);
this.categoriesArrayList = categories;
this.context = context;
itemView.setOnClickListener(this);
this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
}
@Override
public void onClick(View v) {
int position = getAdapterPosition();
Category category = this.categoriesArrayList.get(position);
Toast.makeText(context, ""+category.getCategoryName() + position,
}
}
As you can see I have implemented OnClickListener
in the holder class and then setTheOnItemClickListner in the Holder.
In my Adapter I pass the holder class the the arraylist with the data like this:
Context context;
ArrayList<Category> categories;
public CategoriesAdapter(Context context, ArrayList<Category> categories) {
this.context = context;
this.categories = categories;
}
@Override
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
CategoryHolder holder = new CategoryHolder(v, context, categories);
return holder;
}
I am passing the data when creating the new holder.
This works fine and I can toast the position and any of the data from the ArrayList
that is used for the RecyclerView
.
What I want to do though is use that in the main fragment where I initialise the RecyclerView
and adapter.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_nested_youtube_video_selection, container, false);
//////////////////////////// CATEGORIES RECYCLER /////////////////////////////////////
// Initialise the categories Recylerview
LinearLayoutManager categoriesLayoutManger = new LinearLayoutManager(getActivity());
categoriesLayoutManger.setOrientation(LinearLayoutManager.HORIZONTAL);
categoriesRecyclerView = (RecyclerView) view.findViewById(R.id.youtubeAlarmCategoryRecyclerView);
categoriesRecyclerView.setLayoutManager(categoriesLayoutManger);
// Get the data for the categories RecyclerView
categoryArraylist = CategoryCollection.getCategoryArrayList();
// Initialse the categories RecyclerView Adapter
categoriesAdapter = new CategoriesAdapter(getActivity(), categoryArraylist);
// Bind the categories Adapter to the categories RecyclerView
categoriesRecyclerView.setAdapter(categoriesAdapter);
I am thinking I need an interface but I am not sure how to do that or if that is even the best way to do it.
Following should work:
onClickListener
that passes the event on to the interfaceHere's an example:
Interface
public interface ItemClickListener {
void onItemClicked(ViewHolder vh, Object item, int pos);
}
public interface GenericItemClickListener<T, VH extends ViewHolder> {
void onItemClicked(VH vh, T item, int pos);
}
ViewHolder
public class CategoryHolder extends RecyclerView.ViewHolder {
public CategoryHolder(View itemView, Context context) {
super(itemView);
this.context = context;
this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
}
}
Adapter
Context context;
ArrayList<Category> categories;
ItemClickListener itemClickListener;
public CategoriesAdapter(Context context, ArrayList<Category> categories, ItemClickListener itemClickListener) {
this.context = context;
this.categories = categories;
this.itemClickListener = itemClickListener;
}
// DON'T PASS YOUR DATA HERE, just create a ViewHolder
@Override
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
CategoryHolder holder = new CategoryHolder(v, context);
return holder;
}
//HERE you bind one item of your list to the view holder
@Override
public void onBindViewHolder(final CategoryHolder vh, final int i) {
final Category category = categories.get(i);
// set click listener
vh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
itemClickListener.onItemClicked(vh, category, i);
}
});
// update images and texts...
}
Edit
Updated the code to show you, that you should not pass a array of items to every view holder... The view holder gets created and reused, only update the view holder in onBindViewHolder
and bind the view holder instance to the correct data there...
Btw, I would make a generic interface instead, that's even more beautiful... My example is just a simple solution...
Edt 2 - How to create the interface instance
ItemClickListener listener = new ItemClickListener(){
@Override
public void onItemClicked(RecyclerView.ViewHolder vh, Object item, int pos){
Toast.makeText(getActivity(), "Item clicked: " + pos, Toast.LENGTH_SHORT).show();
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With