Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an addHeaderView equivalent for RecyclerView?

I'm looking for an equivalent to addHeaderView for a recycler view. Basically I want to have an image with 2 buttons be added as a header to the listview. Is there a different way to add a header view to a recycler view? An example for guidance would be helpful

EDIT 2 (added fragment layouts):

After adding log statements, it seems as though getViewType only ever receives a position of 0. This leads to onCreateView only loading the one layout:

10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> onCreateViewHolder, viewtype: 0 10-26 16:32:53.766    5449-5449/co.testapp I/logger info﹕ Adapter-> onBindViewHolder, viewType: 0 

The fragment transition to load the CommentFragment:

@Override public void onPhotoFeedItemClick(View view, int position) {     if (fragmentManager == null)         fragmentManager = getSupportFragmentManager();  FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();      if (view.getId() == R.id.button_comment){         CommentFragment commentFragment = CommentFragment.newInstance("","", position);         fragmentTransaction.add(R.id.main_activity, commentFragment,"comment_fragment_tag");         fragmentTransaction.addToBackStack(Constants.TAG_COMMENTS);         fragmentTransaction.commit();     } } 

The Fragment's onCreateView:

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,                          Bundle savedInstanceState) {      View view = inflater.inflate(R.layout.fragment_comment, container, false);     mRecyclerView = (RecyclerView) view.findViewById(R.id.list_recylclerview);     mRecyclerView.setLayoutManager(new LinearLayoutManager(_context));     mRecyclerView.setItemAnimator(new DefaultItemAnimator());     mAdapter = new CommentAdapter(R.layout.row_list_comments, R.layout.row_header_comments, _context, comments);     mRecyclerView.setAdapter(mAdapter);     return view; } 

The fragment containing the recycleview:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     tools:context="co.testapp.fragments.CommentFragment"     android:background="@color/white">         <RelativeLayout             android:layout_width="fill_parent"             android:layout_height="fill_parent"             android:orientation="vertical">             <android.support.v7.widget.RecyclerView                 xmlns:android="http://schemas.android.com/apk/res/android"                 android:id="@+id/list_recylclerview"                 android:layout_width="match_parent"                 android:layout_height="200dp" />         </RelativeLayout> </RelativeLayout> 

The comments row layout:

<?xml version="1.0" encoding="utf-8"?>  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="vertical" android:layout_width="match_parent"     android:layout_height="match_parent" android:layout_margin="10dp"     android:background="@color/white">     <!--Profile Picture-->     <ImageView         android:layout_width="80dp"         android:layout_height="80dp"         android:id="@+id/profile_picture"         android:background="@color/blue_testapp"/>     <!--Name-->     <TextView         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_marginLeft="10dp"         android:text="First Name Last Name"         android:textSize="16dp"         android:textColor="@color/blue_testapp"         android:id="@+id/name_of_poster"         android:layout_toRightOf="@id/profile_picture"         />     <!--Comment-->     <TextView         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_margin="10dp"         android:layout_marginTop="-5dp"         android:text="This is a test comment"         android:textSize="14dp"         android:textColor="@color/black"         android:id="@+id/comment"         android:layout_below="@id/name_of_poster"         android:layout_toRightOf="@id/profile_picture"/> </RelativeLayout> 

The header

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"               android:orientation="vertical"               android:layout_width="match_parent"               android:layout_height="match_parent">     <ImageView         android:layout_width="wrap_content"         android:layout_height="300dp"         android:id="@+id/header_photo"         android:layout_gravity="center_horizontal"/> </LinearLayout> 

The Adapter code (thanks to hister for getting me started):

public class CommentAdapter extends RecyclerView.Adapter<ViewHolder>{      private final int rowCardLayout;     public static Context mContext;     private final int headerLayout;     private final String [] comments;     private static final int HEADER = 0;     private static final int OTHER = 1;      public CommentAdapter(int rowCardLayout, int headerLayout, Context context, String [] comments) {         this.rowCardLayout = rowCardLayout;         this.mContext = context;         this.comments = comments;         this.headerLayout = headerLayout;     }      @Override     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {         logger.i("onCreateViewHolder, viewtype: " + i); //viewtype always returns 0 so OTHER layout is never inflated         if (i == HEADER) {             View v = LayoutInflater.from(viewGroup.getContext()).inflate(headerLayout, viewGroup, false);             return new ViewHolderHeader(v);         }         else if (i == OTHER){             View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowCardLayout, viewGroup, false);             return new ViewHolderComments(v);         }         else            throw new RuntimeException("Could not inflate layout");     }      @Override     public void onBindViewHolder(ViewHolder viewHolder, int i) {         logger.i("onBindViewHolder, viewType: " + i);          if (viewHolder instanceof ViewHolderComments)             ((ViewHolderComments) viewHolder).comment.setText(comments[i].toString());         if (viewHolder instanceof ViewHolderHeader)            ((ViewHolderHeader) viewHolder).header.setImageResource(R.drawable.image2);         else {             logger.e("no instance of viewholder found");         }     }      @Override     public int getItemCount() {         int count = comments.length + 1;         logger.i("getItemCount: " + count);         return count;     }      @Override     public int getItemViewType(int position) {         logger.i("getItemViewType position: " + position);         if (position == HEADER)             return HEADER;         else             return OTHER;     }      public static class ViewHolderComments extends RecyclerView.ViewHolder {         public TextView comment;         public ImageView image;          public ViewHolderComments(View itemView) {             super(itemView);             comment = (TextView) itemView.findViewById(R.id.comment);             image = (ImageView) itemView.findViewById(R.id.image);         }     }      public static class ViewHolderHeader extends RecyclerView.ViewHolder {         public final ImageView header;          public ViewHolderHeader(View itemView){             super(itemView);             header = (ImageView) itemView.findViewById(R.id.header_photo);         }     } } 

Using the above code, only the header layout is displayed as viewType is always 0. It looks like this. If I force the other layout it looks like this:

like image 542
ViciDroid Avatar asked Oct 23 '14 14:10

ViciDroid


People also ask

What did RecyclerView replace?

RecyclerView is a somewhat new view that came to substitute the ListView and GridView. From its documentation, you can see that it is a more efficient and advanced widget when compared to its predecessors, despite having many simplifications to support better animations and better arrangements of elements.

What is difference between CardView and RecyclerView?

The RecyclerView is a more advanced and more flexible version of the ListView. This new component is a big step because the ListView is one of the most used UI widgets. The CardView widget, on the other hand, is a new component that does not “upgrade” an existing component.

What are differences between RecyclerView adapter and Listadapter?

RecyclerView has greater support for LayoutManagement including vertical lists, horizontal lists, grids and staggered grids. ListView only supports vertical lists. ListView starts by default with dividers between items and requires customisation to add decorations.

What is setHasFixedSize in RecyclerView?

setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height. This allows the RecyclerView to optimize better by figuring out the exact height and width of the entire list based on the your adapter.


1 Answers

There isn't an easy way like listview.addHeaderView() but you can achieve this by adding a type to your adapter for header.

Here is an example

public class HeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {     private static final int TYPE_HEADER = 0;     private static final int TYPE_ITEM = 1;     String[] data;      public HeaderAdapter(String[] data) {         this.data = data;     }      @Override     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         if (viewType == TYPE_ITEM) {             //inflate your layout and pass it to view holder             return new VHItem(null);         } else if (viewType == TYPE_HEADER) {             //inflate your layout and pass it to view holder             return new VHHeader(null);         }          throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");     }      @Override     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {         if (holder instanceof VHItem) {             String dataItem = getItem(position);             //cast holder to VHItem and set data         } else if (holder instanceof VHHeader) {             //cast holder to VHHeader and set data for header.         }     }      @Override     public int getItemCount() {         return data.length + 1;     }      @Override     public int getItemViewType(int position) {         if (isPositionHeader(position))             return TYPE_HEADER;          return TYPE_ITEM;     }      private boolean isPositionHeader(int position) {         return position == 0;     }      private String getItem(int position) {         return data[position - 1];     }      class VHItem extends RecyclerView.ViewHolder {         TextView title;          public VHItem(View itemView) {             super(itemView);         }     }      class VHHeader extends RecyclerView.ViewHolder {         Button button;          public VHHeader(View itemView) {             super(itemView);         }     } } 

link to gist -> here

like image 77
EC84B4 Avatar answered Sep 21 '22 14:09

EC84B4