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:
create an interface
create an instance of this interface in your fragment and pass it on to the adapter
let the adapter pass this interface on to the view holder
let the view holder define an onClickListener that passes the event on to the interface
Here'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();
}
};
abstract YOURAdapter class then add method like
void onLikeClicked(Object object, int position);
void onItemClicked();
call it in bindView as simply like
holder.btnLike.setOnclickListner(new OnClickListner){
onLikeClicked(list.get(position), position);
}
In Activity Class
now it will automatically implements all methods of adapter
YOURAdapter adapter=new YOURAdapter(){
void onLikeClicked(Object object, int position){
}
void onItemClicked(){
}
}
Related
Due to the fact that the ListView is not optimized enough, I decided that I would switch to the Recycler View. The first problem that hit me was this one.
My RecyclerView adapter:
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private List<String> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
MyRecyclerViewAdapter(Context context, List<String> data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.adapter_box, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
String animal = mData.get(position);
holder.myTextView.setText(animal);
}
// total number of rows
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.text_adapter);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
String getItem(int id) {
return mData.get(id);
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
Using ListView I could do like this:
ListView listView = findViewById(R.id.testL);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (parent.getItemAtPosition(position).equals("hello")) {
TextView details = word_dialog.findViewById(R.id.word_edit_desc);
details.setText("hello");
}
}
});
How can I achieve the same result, but only with the Recycle view?:
#Override
public void onItemClick(View view, int position) {
}
I will be very grateful if you can help me!
I want to be able to click on the recycler view items in MainActivity.java, I already did it, now I need to be able to do my own actions on each line sorted using equals
ArrayList<String> animalNames = new ArrayList<>();
animalNames.add("Dog");
animalNames.add("Cow");
animalNames.add("Camel");
animalNames.add("Sheep");
animalNames.add("Goat");
// set up the RecyclerView
recyclerView = findViewById(R.id.myList);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyRecyclerViewAdapter(this, animalNames);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
if (somecode.equals("Dog")){
soundPlay(MediaPlayer.create(getBaseContext(), R.raw.star));
}
if (somecode.equals("Camel")){
soundPlay(MediaPlayer.create(getBaseContext(), R.raw.tick));
}
You can define an interface in your adapter, like below
public interface ClickListener{
void onClick();
}
Implement in fragment or activity that your adapter at:
ClickListener listener = () ->{
TextView details = word_dialog.findViewById(R.id.word_edit_desc);
details.setText("hello");
}
then pass interface to adapter use constructor or setter, and you can use interface in your viewHolder when bind like below:
itemView.setOnClickListener(()->{
if (your_list.get(getAdapterPosition()).equals("hello")) {
interface_var_name.onClick()
}
});
This is Inbuild Click event of Recyclerview and another way to use Interface
holder.itemView.setOnClickListener(v ->
if (animal.equals("Your animal String"){
//Your code
}
);
if want to use interface then this is reference link
I want to make a dialog that pops up if you click on a Name TextView in my ListView.
So I've been following this youtube tutorial: https://www.youtube.com/watch?v=ARezg1D9Zd0&t=511s and he makes a dialog that pops up from his MainActivity. But I want to pop it up from my ListView, so from my Adapter.
Because of that I can't call getSupportFragmentManager(). I think it's because my Adapter does extend ArrayAdapter<> instead of AppCompatActivity. Can anyone help me?
It goes wrong when I say: changeNameDialog.show(getSupportFragmetnManager(), "Change Name Dialog");
public class PlayersAdapter extends ArrayAdapter<Player> {
Tournament tournament = new Tournament();
private LayoutInflater Inflater;
public PlayersAdapter(#NonNull Context context, #NonNull List<Player> objects) {
super(context, R.layout.list_players,objects);
Inflater = LayoutInflater.from(context);
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
if (convertView == null) {
convertView = Inflater.inflate(R.layout.list_players, parent, false);
}
ImageView profilePictureButtonImageView = convertView.findViewById(R.id.profilePictureButtonImageView);
TextView namePlayerTextView = convertView.findViewById(R.id.namePlayerTextView);
TextView pointsTextView = convertView.findViewById(R.id.pointsTextView);
ImageView deleteButtonImageView = convertView.findViewById(R.id.deleteButtonImageView);
Player player = getItem(position);
profilePictureButtonImageView.setImageResource(player.getProfilePicture());
namePlayerTextView.setText(player.getName());
pointsTextView.setText(tournament.getPlayers().get(position).getTotalPoints() + "");
// Change name
namePlayerTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ChangeNameDialog changeNameDialog = new ChangeNameDialog();
changeNameDialog.show(getSupportFragmetnManager(), "Change Name Dialog");
}
});
return convertView;
}
}
Create an interface with a method in your Adapter class as follows:
public interface OnAdapterInteractionListener {
void showDialog();
}
Change the constructor of your Adapter class and receive your Activity / Fragment as OnAdapterInteractionListener in it. Save it as a global variable in your Adapter class. While calling this constructor from your Activity or Fragment, pass on this for OnAdapterInteractionListener.
private LayoutInflater Inflater;
private OnAdapterInteractionListener mListener;
public PlayersAdapter(#NonNull Context context, #NonNull List<Player> objects, OnAdapterInteractionListener listener) {
super(context, R.layout.list_players,objects);
Inflater = LayoutInflater.from(context);
mListener = listener;
}
Make your Activity / Fragment implement the adapter interface OnAdapterInteractionListener and implement its method as follows:
#Override
public void showDialog() {
ChangeNameDialog changeNameDialog = new ChangeNameDialog();
changeNameDialog.show(getSupportFragmentManager(), "Change Name Dialog");
}
Finally, in your Adapter, amend your onClick() method as follows:
namePlayerTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mListener != null) mListener.showDialog();
}
});
Hope it serves your purpose!
I'm trying to populate a RecyclerView using data stored in a ArrayList. When the RecyclerView loads each piece of data is repeted 4x in each row.
I've tried a whole variety of solutions I've found, but none seem to resolve the issue.
After some debugging the data in 'mData', appears to be correct, so that would lead me to believe that this issue is 'onBindViewHolder'?
Adapter
public class EventsRecyclerViewAdapter extends RecyclerView.Adapter<EventsRecyclerViewAdapter.ViewHolder> {
private List<String> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
public EventsRecyclerViewAdapter(List<String> data) {
this.mInflater = LayoutInflater.from(MainActivity.mainActivity);
this.mData = data;
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.keyID.setText(mData.get(position));
holder.lockID.setText(mData.get(position));
holder.eventTime.setText(mData.get(position));
holder.eventType.setText(mData.get(position));
}
// total number of rows
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView keyID;
TextView lockID;
TextView eventTime;
TextView eventType;
ViewHolder(View itemView) {
super(itemView);
keyID = itemView.findViewById(R.id.keyIDTV);
lockID = itemView.findViewById(R.id.lockIDTV);
eventTime = itemView.findViewById(R.id.eventDateTV);
eventType = itemView.findViewById(R.id.eventTypeTV);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
Fragment
public class KeyEvents extends Fragment {
public static KeyInfo newInstance() {
KeyInfo fragment = new KeyInfo();
return fragment;
}
EventsRecyclerViewAdapter adapter;
ArrayList<String> eventsList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventsOperationHandler ev = new EventsOperationHandler();
eventsList = new ArrayList<>();
for (int i=0; i<ev.getEvents().size(); i++) {
eventsList.add(ev.getEvents().get(i).get(0));
eventsList.add(ev.getEvents().get(i).get(1));
eventsList.add(ev.getEvents().get(i).get(2));
eventsList.add(ev.getEvents().get(i).get(3));
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_event_info, container, false);
RecyclerView recyclerView = view.findViewById(R.id.rvEvents);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.mainActivity));
adapter = new EventsRecyclerViewAdapter(eventsList);
recyclerView.setAdapter(adapter);
return view;
}
}
In your 'onBindViewHolder' you are setting same data in every textView of yours
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.keyID.setText(mData.get(position));
holder.lockID.setText(mData.get(position));
holder.eventTime.setText(mData.get(position));
holder.eventType.setText(mData.get(position));
}
Here you are setting mData.get(position) to every textView in the holder
A solution would be creating a Pojo class for your recyclerView
Create Pojo Event class
class Event{
public String keyID;
public String lockID;
public String eventTime;
public String eventType;
}
Create a list of 'Event' in your fragment
public class KeyEvents extends Fragment {
public static KeyInfo newInstance() {
KeyInfo fragment = new KeyInfo();
return fragment;
}
EventsRecyclerViewAdapter adapter;
ArrayList<Event> eventsList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventsOperationHandler ev = new EventsOperationHandler();
eventsList = new ArrayList<>();
for (int i=0; i<ev.getEvents().size(); i++) {
Event event = new Event();
event.keyID = ev.getEvents().get(i).get(0);
event.lockID = ev.getEvents().get(i).get(1);
event.eventTime = ev.getEvents().get(i).get(2);
event.eventType = ev.getEvents().get(i).get(3);
eventsList.add(event);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_event_info, container, false);
RecyclerView recyclerView = view.findViewById(R.id.rvEvents);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.mainActivity));
adapter = new EventsRecyclerViewAdapter(eventsList);
recyclerView.setAdapter(adapter);
return view;
}
}
Modify your recyclerView to handle to 'Event' class
public class EventsRecyclerViewAdapter extends RecyclerView.Adapter<EventsRecyclerViewAdapter.ViewHolder> {
private List<Event> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
public EventsRecyclerViewAdapter(List<Event> data) {
this.mInflater = LayoutInflater.from(MainActivity.mainActivity);
this.mData = data;
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Event event = mData.get(position);
holder.keyID.setText(event.keyID);
holder.lockID.setText(event.lockId);
holder.eventTime.setText(event.eventTime);
holder.eventType.setText(event.eventType);
}
// total number of rows
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView keyID;
TextView lockID;
TextView eventTime;
TextView eventType;
ViewHolder(View itemView) {
super(itemView);
keyID = itemView.findViewById(R.id.keyIDTV);
lockID = itemView.findViewById(R.id.lockIDTV);
eventTime = itemView.findViewById(R.id.eventDateTV);
eventType = itemView.findViewById(R.id.eventTypeTV);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
That's it, this should work perfectly.
I created an app which displays all files from internal storage in gridview using recyclerviewadapter. But I am not sure how to display different icons for different file types. I want to achieve somewhat this kind of view. Like it has different icon for a folder, different for a pdf file, or an image. How can I achieve this ?
InternalStorage.java:
public class InternalStorage extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {
MyRecyclerViewAdapter adapter;
private ArrayList<String> myList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_internal_storage);
myList = new ArrayList<>();
String path= Environment.getExternalStorageDirectory().getAbsolutePath();
File f = new File(path);//converted string object to file
File list[] = f.listFiles();//getting the list of files in string array
for( int i=0; i< list.length; i++) {
myList.add(list[i].getName());
}
// set up the RecyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rvNumbers);
int numberOfColumns = 4;
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
adapter = new MyRecyclerViewAdapter(this, myList);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
}
}
MyRecyclerViewAdapter.java:
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private ArrayList<String> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
public MyRecyclerViewAdapter(Context context, ArrayList<String> data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// inflates the cell layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
return new ViewHolder(view);
}
// binds the data to the textview in each cell
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
String animal = mData.get(position);
holder.myTextView.setText(animal);
}
// total number of cells
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ImageButton myImage;
ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.info_text);
myImage = (ImageButton) itemView.findViewById(R.id.buttonimage);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
public String getItem(int id) {
return mData.get(id);
}
// allows clicks events to be caught
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
first of all you need to creat a model than allows you to diferentiate each animal from the others. You can do it with a model wich has a name and a imageUrl (an image url to each animal than you can set depending of the type of the animal). After that you must define a imageView who will have the new image (the one that will be inflatin with the image you bring from the url). To load the image i recomend to you to use Picasso, whihc is a library that makes easier to load any kind of imagen.
The code is somethin like this
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private ArrayList<Animal> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
public MyRecyclerViewAdapter(Context context, ArrayList<String> data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// inflates the cell layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
return new ViewHolder(view);
}
// binds the data to the textview in each cell
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Animal animal = mData.get(position);
holder.myTextView.setText(animal);
Picasso.with(context).load(animal.imageUrl).into(holder.imageViewYouWantToChangue)
}
// total number of cells
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ImageButton myImage;
ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.info_text);
myImage = (ImageButton) itemView.findViewById(R.id.buttonimage);
imageViewYouWantToChangue = (ImageView) itemView.findViewById(R.id.image_you_to_changue);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
public String getItem(int id) {
return mData.get(id);
}
// allows clicks events to be caught
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}}
public class Animal{
String name;
String imageUrl;
public Animal(String name, String type) {
this.name = name;
this.imageUrl = imageUrl;
}
}
The info about picasso
http://square.github.io/picasso/
And don't forget to add the INTERNET_PERMISION to you app in the manifest.
As you can see in the screenshot, my project contains a RecyclerView (for categories of food) which contains more RecyclerViews (for the ingredients). But iv'e got a problem, my RecyclerView is messing up the order. I debuged the project and the parameters are just fine but the RecyclerView is displaying them wrong. As you can see in the picture, Fruits ingredients are displayed in the Dairy category.
IngredientSectionAdapter.Java
(the main adapter,which contain more RecyclerViews)
class SectionViewHolder extends RecyclerView.ViewHolder {
private TextView sectionBtn;
private RecyclerView itemRecyclerView;
public SectionViewHolder(View itemView) {
super(itemView);
sectionBtn = (TextView) itemView.findViewById(R.id.text_category);
itemRecyclerView = (RecyclerView) itemView.findViewById(R.id.ingredientsRecycler);
}
}
private Context context;
private ArrayList<IngredientSectionModel> sectionModelArrayList;
ArrayList<IngredientItemAdapter> adapters;
public IngredientSectionAdapter(Context context, ArrayList<IngredientSectionModel> sectionModelArrayList) {
this.context = context;
this.sectionModelArrayList = sectionModelArrayList;
adapters = new ArrayList<IngredientItemAdapter>();
}
#Override
public SectionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.parent_list,null);
return new SectionViewHolder(v);
}
#Override
public void onBindViewHolder(SectionViewHolder holder, int position) {
final IngredientSectionModel sectionModel = sectionModelArrayList.get(position);
holder.itemRecyclerView.setTag(holder.itemRecyclerView.getVisibility());
final RecyclerView sectionList = holder.itemRecyclerView;
holder.sectionBtn.setText(sectionModel.getSectionLabel());
//recycler view for items
holder.itemRecyclerView.setHasFixedSize(true);
holder.itemRecyclerView.setNestedScrollingEnabled(false);
/* set layout manager on basis of recyclerview enum type */
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3,1);
adapters.add(new IngredientItemAdapter(context, sectionModel.getItemArrayList()));
int resId = R.anim.grid_layout_animation_from_bottom;
//LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(context, resId);
holder.itemRecyclerView.setLayoutManager(staggeredGridLayoutManager);
holder.itemRecyclerView.setAdapter(adapters.get(position));
//holder.itemRecyclerView.setLayoutAnimation(animation);
//toggle visibilty of inner RecyclerView (ingredients, not categories)
holder.sectionBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (sectionList.getVisibility() == View.VISIBLE){
sectionList.setVisibility(View.GONE);
}
else
{
sectionList.setVisibility(View.VISIBLE);
}
}
});
}
What can cause this?
Every time onBindViewHolder is called you create a new IngredientItemAdapter and add it to your adapters, and then you call holder.itemRecyclerView.setAdapter(adapters.get(position)). However, adapters.get(position) is not the adapter you just created. Your adapter will get bigger and bigger. Try this
IngredientItemAdapter adapter = adapters.get(position);
adapter.setIngredients(sectionModel.getItemArrayList());
holder.itemRecyclerView.setAdapter(adapter);