Android - Using RecyclerView with default Adapters - java

Is it possible to use default Adapters for RecyclerView? ArrayAdapter, for example (without creating own classes?)
Is there sense to use RecyclerView with just one line of text per item? ListView can do it without any extra classes.

Here is a default ArrayAdapter implementation for the RecyclerView
https://github.com/passsy/ArrayAdapter
Sample implementation:
public class UserAdapter extends ArrayAdapter<User, UserAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView titleView;
public ViewHolder(final View itemView) {
super(itemView);
titleView = (TextView) itemView.findViewById(R.id.title);
}
}
#Nullable
#Override
public Object getItemId(#NonNull final User user) {
return user.getId();
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final User item = getItem(position);
holder.titleView.setText(item.getName());
}
#Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.itemview_user, parent, false);
return new ViewHolder(view);
}
}

Related

Facing error in onBindView() method in recyclerView

I am just practicing the RecyclerView. when I run the App my App crashed I check the log but i cant understand the problem can some help me im waiting for someone responce?
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private model[] localDataSet;
private TextView name,number;
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
public ViewHolder(View view) {
super(view);
textView = (TextView) view.findViewById(R.id.name);
}
public TextView getTextView() {
return textView;
}
}
public CustomAdapter(model[] dataSet) {
localDataSet = dataSet;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
// Create a new view, which defines the UI of the list item
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.contacx, viewGroup, false);
view.findViewById(R.id.name);
view.findViewById(R.id.number);
return new ViewHolder(view);
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
name.setText(localDataSet[position].getName());
number.setText(localDataSet[position].getPhone());
}
#Override
public int getItemCount() {
return localDataSet.length;
}
}
You need to change the following things in your code:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private model[] localDataSet;
//remove this from here.
//private TextView name,number;
public static class ViewHolder extends RecyclerView.ViewHolder {
//This should be from the layout you have passed in ViewHolder method. in your case from R.layout.contacx. This layout should have two textview with ids:- name and phone respectively.
private final TextView name, phone;
public ViewHolder(View view) {
super(view);
name = view.findViewById(R.id.name);
phone = view.findViewById(R.id.phone);
}
}
public CustomAdapter(model[] dataSet) {
localDataSet = dataSet;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
// Create a new view, which defines the UI of the list item
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.contacx, viewGroup, false);
//remvoe this from here.
//view.findViewById(R.id.name);
//view.findViewById(R.id.number);
return new ViewHolder(view);
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
//here you should call those view to bind your data like:
viewHolder.name.setText(localDataSet[position].getName());
viewHolder.phone.setText(String.valueOf(localDataSet[position].getPhone()));
}
#Override
public int getItemCount() {
return localDataSet.length;
}
}
Use ViewHolder for data bind. More safe
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private model[] localDataSet;
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView name, number;
public ViewHolder(View view) {
super(view);
name = view.findViewById(R.id.name);
number = view.findViewById(R.id.phone);
}
public void bindData(model data) {
name.setText(data.getName());
number.setText(String.valueOf(data.getPhone()));
}
}
public CustomAdapter(model[] dataSet) {
localDataSet = dataSet;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
/* No Need
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.contacx, viewGroup, false);
view.findViewById(R.id.name);
view.findViewById(R.id.number);
*/
return new ViewHolder(LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.contacx, viewGroup, false););
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
/*
name.setText(localDataSet[position].getName());
number.setText(localDataSet[position].getPhone());
*/
viewHolder.bindData(localDataSet[position]);
}
#Override
public int getItemCount() {
return localDataSet.length;
}
}

Multiple recyclerviews using one adapter

I have an app where I want to use recyclerviews in different parts of the application and I was thinking of using the same adapter for the same two (or more) recyclerviews, I was thinking this would be a good practice, or am I mistaken and better off making a new adapter for every recyclerview in the app?
Here is the code for my adapter:
public class RecyclerViewAdapter extends RecyclerView.Adapter <RecyclerViewAdapter.MyViewHolder> {
private ArrayList<Task> list;
//This is the list of the second recyclerview which I want to implement
private ArrayList<String> categories;
private OnItemListener mOnItemListener;
RecyclerViewAdapter(ArrayList<Task> list, OnItemListener onItemListener)
{
this.list = list;
this.mOnItemListener = onItemListener;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
TextView textView = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.single_view, parent, false);
return new MyViewHolder(textView, mOnItemListener);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.textView.setText(list.get(position).getTaskName());
}
#Override
public int getItemCount() {
return list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
TextView textView;
OnItemListener onItemListener;
MyViewHolder(#NonNull View itemView, OnItemListener onItemListener) {
super(itemView);
textView = itemView.findViewById(R.id.singleView);
this.onItemListener = onItemListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v)
{
onItemListener.onItemClick(getAdapterPosition());
}
}
public interface OnItemListener
{
void onItemClick(int position);
}
}
So how would I go about doing this so that it can switch depending on which recyclerview in the app is setting/initializing the adapter, so that the getItemCount for example, would return the size of categories instead of list and so on.

What might be the problem with my adapter i seem not to find it``

The view seems not to bind to the ArrayList(ie private ArrayList mEvents;) that i passed to the class ,on the onBindViewHolder(ie holder.mTextView2.setText(current.getcity());) i can seem to access the textView variables(ie public TextView mTextview2;), that i declared in the view holder class. I have tried to make the variables as a member variable but it seems not to work well
public class eventsAdapter extends RecyclerView.Adapter {
private ArrayList<recycleview_items> mEvents;
public eventsAdapter(ArrayList<recycleview_items> passedArray){
//constructor for the adapter calls for which i created
mEvents = passedArray;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//we pass the layout of our card to the adapter here
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_listitem, parent, false);
eventViewHolder events = new eventViewHolder(v);
return events;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
//we pass data from the array list we created to the views
recycleview_items current = mEvents.get(position);
holder.mImageView.setImageResource(current.getImageResource());
holder.mTextView1.setText(current.getname());
holder.mTextView2.setText(current.getcity());
}
#Override
public int getItemCount() {
return mEvents.size();
};
public static class eventViewHolder extends RecyclerView.ViewHolder{
public ImageView mImageview ;
public TextView mTextview;
public TextView mTextview2;
public eventViewHolder(#NonNull View itemView) {
super(itemView);
mImageview = itemView.findViewById(R.id.ImageView1);
mTextview = itemView.findViewById(R.id.text_view1);
mTextview2 = itemView.findViewById(R.id.text_view2);
}
}
}
public class eventsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<recycleview_items> mEvents;
public eventsAdapter(ArrayList<recycleview_items> passedArray){
//constructor for the adapter calls for which i created
mEvents = passedArray;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//we pass the layout of our card to the adapter here
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_listitem, parent, false);
eventViewHolder events = new eventViewHolder(v);
return events;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
//we pass data from the array list we created to the views
recycleview_items current = mEvents.get(position);
holder.bind(current);
}
#Override
public int getItemCount() {
return mEvents.size();
};
class eventViewHolder extends RecyclerView.ViewHolder{
public ImageView mImageview ;
public TextView mTextview;
public TextView mTextview2;
public eventViewHolder(#NonNull View itemView) {
super(itemView);
mImageview = itemView.findViewById(R.id.ImageView1);
mTextview = itemView.findViewById(R.id.text_view1);
mTextview2 = itemView.findViewById(R.id.text_view2);
public void bind(recycleview_items item){
//bind your items here
holder.mImageView.setImageResource(item.getImageResource());
holder.mTextView1.setText(item.getname());
holder.mTextView2.setText(item.getcity());
}
}
}
I've rewritten your code for you with slight modifications.
You should create adapter like this
extends RecyclerView.Adapter<eventsAdapter.eventViewHolder >
Also you should edit
public eventViewHolder onCreateViewHolder
And
onBindViewHolder(eventViewHolder holder, int position)
Try this
public class eventsAdapter extends RecyclerView.Adapter<eventsAdapter.eventViewHolder>{
private ArrayList<recycleview_items> mEvents;
public eventsAdapter(ArrayList<recycleview_items> passedArray){
//constructor for the adapter calls for which i created
mEvents = passedArray;
}
#NonNull
#Override
public eventViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_listitem, parent, false);
return new eventViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull eventViewHolder holder, int position) {
recycleview_items current = mEvents.get(position);
holder.mImageview.setImageResource(current.getImageResource());
holder.mTextview.setText(current.getname());
holder.mTextview2.setText(current.getcity());
}
#Override
public int getItemCount() {
return 0;
}
class eventViewHolder extends RecyclerView.ViewHolder {
ImageView mImageview;
TextView mTextview;
TextView mTextview2;
public eventViewHolder(View itemView) {
super(itemView);
mImageview = itemView.findViewById(R.id.ImageView1);
mTextview = itemView.findViewById(R.id.text_view1);
mTextview2 = itemView.findViewById(R.id.text_view2);
}
}
}
Almost every thing was in Your code that's i have done some modification.
Mate see your Holder View Class name its 'eventViewHolder' and for onBindViewHolder and onCreateViewHolder you're accessing the Recycler.ViewHolder so it's very obvious that you can't access those variable just change this..
#Override
public void onBindViewHolder(#NonNull eventsAdapter.eventViewHolder holder, int position) {
.....
}
and in
#NonNull
#Override
public eventsAdapter.eventViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
......
}

Why is holder.textView accessible directly witout creating an object of the class?

I have this adapter class:
public class ItemAdapter extends PagedListAdapter<Item, ItemAdapter.ItemViewHolder> {
private Context context;
ItemAdapter(Context context) {
this.context = context;
}
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ItemViewHolder holder, int position) {
Item item = getItem(position);
holder.textView.setText(item.name); //Why?!?!
}
class ItemViewHolder extends RecyclerView.ViewHolder {
TextView textView;
ItemViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.name_text_view);
}
}
}
Inside the onBindViewHolder() method, why can I access directly holder.textView since ItemViewHolder is not static? How is this possible to access a field without creating on object of the class?
Just because you're not creating an instance (what you called "object") doesn't mean you aren't using one. In fact, you did create an instance of ItemViewHolder, right in your onCreateViewHolder() method:
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
return new ItemViewHolder(view); //right here
}
The instance returned by onCreateViewHolder() is what's passed to onBindViewHolder() (onCreateViewHolder() and onBindViewHolder() are called for each item in your dataset, so there's a unique-ish instance of ItemViewHolder for each item [RecyclerViews actually recycle ViewHolders, but that's another subject]).
ItemViewHolder.textView
wouldn't work because that is an example of static access.
What you're referencing, though, is an actual instance.
TL;DR, holder is an instance. It's not a static reference.

Using multiple views and data sets in RecyclerView

I have the following adapter which populates a RecyclerView with CardView items containing one TextView. It fills these TextViews with data from a String array. However, now I want to add another TextView to my CardViews and populate it with a separate data array, and I was wondering how I can best achieve this:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private String[] mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(View itemView) {
super(itemView);
mTextView = (TextView)itemView.findViewById(R.id.grade);
}
}
public RecyclerAdapter(String[] myDataset) {
mDataset = myDataset;
}
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
All help is appreciated as always!
Simply add another TextView or any other view in your CardLayout XML R.layout.card_item
Then
public TextView mTextView;
public TextView mTextView1;
public TextView mTextView2;
public TextView mTextView3;
public ViewHolder(View itemView) {
super(itemView);
mTextView = (TextView)itemView.findViewById(R.id.grade);
mTextView1 = (TextView)itemView.findViewById(R.id.grade1);
mTextView2 = (TextView)itemView.findViewById(R.id.grade2);
mTextView3 = (TextView)itemView.findViewById(R.id.grade3);
}
and finally set data to all the desired textviews as
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText("String");
holder.mTextView1.setText("String");
holder.mTextView2.setText("String");
holder.mTextView3.setText("String");
}

Categories

Resources