Create a RecyclerView with multiple view from layouts

recyclerview with multiple layout items - android
recyclerview multiple view types github
recyclerview with multiple sections
android recyclerview multiple view types example
multiple row layouts using recyclerview
two arraylist one recyclerview adapter
recyclerview with multiple view types kotlin
how to use multiple recyclerview in android

I am trying to have 2 layout in one RecyclerView

I have a recycler view list which is called Bookmark and it is parsed from an xml and this is all working , but I wanna in this recyclerview to put another layout which contains a button and that can be clickable. Like in the photo the icons are from recyclerview and the plus button need to be compatible with the list, if the list is larger or smaller the button will be compatible with the space of list.

This is my new code for the Adapter which depends on the answer @LluisFelisart And this is the error ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)

    public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    ArrayList<Bookmark> arrayList = new ArrayList<>();

    public MyAdapter(Context context, ArrayList<Bookmark> arrayList) {
        this.context = context;
        this.arrayList = arrayList;
    }

    public class ViewHolder0 extends RecyclerView.ViewHolder {

        TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
        ImageView tvIcon;

        public ViewHolder0(@NonNull  View itemView) {
            super(itemView);

            tvName=itemView.findViewById(R.id.textView);
            tvIcon = itemView.findViewById(R.id.image_view);
         /*   tvId=itemView.findViewById(R.id.tvId);
            tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
            tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
        }
    }

    public class ViewHolder2 extends RecyclerView.ViewHolder {
        ImageView tvAddBookmark;

        public ViewHolder2(@NonNull View itemView) {
            super(itemView);
            tvAddBookmark = itemView.findViewById(R.id.image_button_add);
        }
    }
    @Override
    public int getItemViewType(int position) {
        // Just as an example, return 0 or 2 depending on position
        // Note that unlike in ListView adapters, types don't have to be contiguous
        return position % 2 * 2;
    }




    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.grid_item, viewGroup, false);

        switch (i) {
            case 0: return new ViewHolder0(viewGroup);
            case 2: return new ViewHolder2(viewGroup);
        }

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        switch (holder.getItemViewType()) {
            case 0:
                ViewHolder0 viewHolder0 = (ViewHolder0) holder;
                ((ViewHolder0) holder).tvName.setText(arrayList.get(position).getName());
                ((ViewHolder0) holder).tvIcon.setImageResource(arrayList.get(position).getIcon());
                break;

            case 2:
                ViewHolder2 viewHolder2 = (ViewHolder2) holder;

        }
        ((ViewHolder0) holder).tvIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent;
                intent = new Intent(context, BookmarkActivity.class);
                v.getContext().startActivity(intent);
            }
        });

        ((ViewHolder0) holder).tvIcon.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Intent intent = new Intent(context, ActivityBookmarksFavorites.class);
                v.getContext().startActivity(intent);
                return false;
            }
        });
    }




    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder  {

        TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
        ImageView tvIcon;

        public ViewHolder(@NonNull  View itemView) {
            super(itemView);

            tvName=itemView.findViewById(R.id.textView);
            tvIcon = itemView.findViewById(R.id.image_view);
         /*   tvId=itemView.findViewById(R.id.tvId);
            tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
            tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
        }



    }



}

This is the grid item layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    android:visibility="visible"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView
        android:id="@+id/image_view"
        style="@style/BookmarkIconIv" />
    <TextView android:id="@+id/textView"
        android:layout_marginTop="1.0dip"
        style="@style/BookmarkTextTv" />
</LinearLayout>

This is the layout of button which I want to be in the recycler view

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageButton
        android:id="@+id/image_button_add"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:src="@drawable/ic_add_black_24dp"
        android:background="@color/transparent" />

</android.support.constraint.ConstraintLayout>

This is the Fragment which the recycler view it is shown

public class FragmentBookmark extends Fragment {
    ArrayList<Bookmark> arrayList = new ArrayList<>();
    XmlPullParser pullParser;
    MyAdapter myAdapter;
    View paramView;
    RecyclerView myRecyclerView;
    private Context mContext;
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }
    @Nullable
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
       paramView = inflater.inflate(R.layout.bookmark, container, false);

        myRecyclerView =  paramView.findViewById(R.id.myRecyclerView);
        myRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 4));
        myRecyclerView.setHasFixedSize(true);
        myAdapter = new MyAdapter(mContext, arrayList);
        myRecyclerView.setAdapter(myAdapter);
        try {
            XmlPullParser xpp = getResources().getXml(R.xml.bookmarks);
            while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
                if (xpp.getEventType() == XmlPullParser.START_TAG) {
                    if (xpp.getName().equals("Bookmark")) {
                        Bookmark bookmark = new Bookmark();
                        bookmark.setName(xpp.getAttributeValue(null, "name"));
                        int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"),"drawable", mContext.getPackageName());
                        bookmark.setIcon(drawableResourceId);
                        arrayList.add(bookmark);
                    }
                }
                xpp.next();
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        myAdapter.notifyDataSetChanged();
        return paramView;
    }
    }

This is the layout bookmark which contains recyclerview

<LinearLayout android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/myRecyclerView"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    android:fillViewport="false">

    </android.support.v7.widget.RecyclerView>

</LinearLayout>

How to create RecyclerView with multiple view type?, getContext()).inflate( R.layout.layout_sample1, parent, false); return new ViewHolder(view); } @Override public void bindViewHolder(ViewHolder holder,  For that, here we will make multiple view holder for the single RecyclerView. Now here we will create a RecyclerView with two different views. One for call layout and another one for email layout.

You can use different layouts on the same RecyclerView , just override adapter getItemViewType() method and return a different int value for the button layout, in your example you should return for example 1 for the normal item and 2 for the button item.

The view type is passed as argument to onCreateViewHolder() method and depending of the viewType value you inflate the normal layout or the button layout.

It seems that you need also make getItemCount() to return one more than the array size

Hope it will help

Here an example: How to create RecyclerView with multiple view type?

Android RecyclerView Example - Multiple ViewTypes, Android RecyclerView example, android recycler view multiple view types We'll be creating three separate ViewHolder classes for each of the above layouts  The RecyclerView Item adapter, this is where the magic happens for having multiple different layouts in the RecyclerView list item. Pay attention to getItemViewType and onCreateViewHolder .

Do this operations in your Activity.

        ArrayList<Bookmark>  data = new ArrayList<>();
        //data.addAll(your array list bookmark); uncomment this line add your all array list of bookmark
        Bookmark d = new Bookmark(0);
        data.add(d);
        mList.setAdapter(new BookMarkAdapter(activity, data));

Try This adapter

public class BookMarkAdapter extends RecyclerView.Adapter {

private Context context;
private ArrayList<Bookmark> data;

public BookMarkAdapter(Context context, ArrayList<Bookmark> data) {
    this.context = context;
    this.data = data;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    if (viewType == 1)
        return new ViewBookmarkHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_with_normal_image_and_textview, parent, false));
    else
        return new AddBookmarkHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_with_image, parent, false));

}


@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

    Bookmark d = data.get(position);

     if (d.getType()==1) {
        ViewBookmarkHolder viewBookmarkHolder =(ViewBookmarkHolder) holder;
        // do your show image and textview operation here
    } else {

        AddBookmarkHolder addBookmarkHolder =(AddBookmarkHolder) holder;
        // do your on click operation here. Like adding new bookmark and update your arraylist and notify data changed for adapter.
    }
}

@Override
public int getItemViewType(int position) {
    return data.get(position).getType();
}

@Override
public int getItemCount() {
    return data.size();
 }
}

Update this methods and variables in your Bookmark Pojo

public class Bookmark {

    private Integer type;

    public Bookmark(Integer type) {
        this.type = type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public Integer getType() {
        if(type==null)
            return 1;
        return type;
    }
  }

Heterogenous Layouts inside RecyclerView, To implement RecyclerView with multiple viewtypes (heterogeneous layouts), most of the work is done within the RecyclerView.Adapter . In particular, there are​  Previously, when I had to implement a feature which contains multiple item view type by using RecyclerView, I’m usually create an adapter with only one ViewHolder class. The code snippet will be

How To Create RecyclerView With Multiple View Types in Android, faced such scenarios where you have to inflate multiple view types in situations where your list might be heterogeneous. Best way to code Heterogenous Layouts inside RecyclerView Create Multiple ViewHolders :. If you want to use different types of row layouts you must to implement next method in adapter: [java] @Override public int getItemViewType(int position) {…} [/java] Firstly we can create two different layouts for our recycler view. item_city [xml] [/xml] item_event [xml] [/xml] Next step is creating a model and dummy data for the application.

Best way to code Heterogenous Layouts inside RecyclerView, To reuse (or recycle) a view, a layout manager may ask the adapter to replace the contents of the view with a different element from the dataset. Recycling views in  Create ViewHolder1 with view layout_viewholder1 for ODD items and ViewHolder2 with view layout_viewholder2 for EVEN ones /** * This method creates different RecyclerView.ViewHolder objects based on the item view type.\ * * @param viewGroup ViewGroup container for the item * @param viewType type of view to be inflated * @return viewHolder to be inflated */ @Override public RecyclerView .

Create a List with RecyclerView, A sample Custom RecyclerView Adapter with View Types in Java Android. how to create a Custom RecyclerView Adapter with Multiple View Types in Java new ViewHolder1(LayoutInflater.from(context).inflate(R.layout.your_list_item_1,  Create a List with RecyclerView Part of Android Jetpack. If your app needs to display a scrolling list of elements based on large data sets (or data that frequently changes), you should use RecyclerView as described on this page. Tip: Start with some template code in Android Studio by clicking File > New > Fragment > Fragment (List).

Comments
  • You can use custom itemViewType and inflate it as an item inside RecyclerView.
  • Can you provide a code how to do this. Or at least give me a help on my code.
  • @Spritzig can u add your code as sample project in Github??
  • I will try to make as sample project in Github
  • @Spritzig ok i'll check it can u explain what issue you are facing in above code and what is your expected output
  • Something it is confusing me here the button view holder ButtonViewHolder buttonViewHolder = (ButtonViewHolder) holder; It is coming the error Cannot cast ViewHolder to ButtonViewHolder
  • @Spritzig kindly please check whole DataAdapter class i have made lots of change in that adapter class
  • @Spritzig welcome happy to help you
  • can you help me in one another problem which I have, you know you have answered me with parsing the datas from an xml, do you know how to add now new data there, I have a layout which I can put string and save with shared preferences but I dont know how to show in the recyclerview list.
  • @Spritzig you can not add new data inside res folder at runtime
  • Thank you for the answer but I am little confused can you provide a code about your answer?
  • I have added the code but it is not working, I am changing the code to see what I have done wrong.