Intereting Posts
Установка apk с веб-страницы Как скрыть вкладку в макете вкладки Android? Как получить статус устройства Android (офлайн или онлайн) с помощью GCM? OnResume вызывается снова и снова, когда экран телефона заблокирован Что такое окно Android? Как я могу изменить голос звонка по запросу в Android? (Сменить человека на женщину и т. Д.) SyncAdapter-onPerformSync не имеет доступа в Интернет Ошибки из памяти возникают с большим размером кучи, но с небольшим выделенным размером. Зачем? Android Crash, java.lang.IllegalArgumentException: тип окна не может быть изменен после добавления окна Программно подключаться к устройству Android в переносной точке доступа Местоположение Google Play Не подключено. Вызовите connect () и дождитесь, когда onConnected () будет вызван Доступ к пользовательским объектам в виде списка Android Создание гибкого XML, состоящего из нескольких растровых изображений Holoeverywhere: как программно удалить во время выполнения панель действий из активности Android: NoClassDefFound

Есть ли эквивалент addHeaderView для RecyclerView?

Я ищу эквивалент addHeaderView для просмотра ресайклеров. В принципе, я хочу, чтобы изображение с двумя кнопками было добавлено в виде заголовка в список. Есть ли другой способ добавить представление заголовка в вид ресайклера? Примером для руководства было бы полезно

EDIT 2 (добавленные макеты фрагментов):

После добавления операторов журналов кажется, что getViewType только когда-либо получает позицию 0. Это приводит к тому, что onCreateView загружает только один макет:

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 

Переход фрагмента для загрузки 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(); } } 

Фрагмент 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; } 

Фрагмент, содержащий 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> 

Макет строки комментариев:

 <?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> 

Заголовок

 <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> 

Код адаптера (спасибо его за то, что он начал меня):

 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 = 0; 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); } } } 

Используя приведенный выше код, отображается только макет заголовка, поскольку viewType всегда равен 0. Он выглядит так. Если я заставляю другой макет, он выглядит так:

Solutions Collecting From Web of "Есть ли эквивалент addHeaderView для RecyclerView?"

Существует не так просто, как listview.addHeaderView() но вы можете добиться этого, добавив тип в свой адаптер для заголовка.

Вот пример

  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); } } } 

Ссылка на gist -> здесь

Не стесняйтесь использовать мою библиотеку, доступную здесь .

Это позволит вам создать заголовок View для любого RecyclerView который использует LinearLayoutManager или GridLayoutManager с помощью простого вызова метода.

Введите описание изображения здесь

Легкий и многоразовый ItemDecoration

Статические заголовки могут быть легко добавлены с помощью ItemDecoration и без каких-либо дальнейших изменений.

 // add the decoration. done. HeaderDecoration headerDecoration = new HeaderDecoration(/* init */); recyclerView.addItemDecoration(headerDecoration); 

Украшение также можно использовать повторно, так как нет необходимости изменять адаптер или RecyclerView вообще.

Пример кода, приведенный ниже, потребует просмотра для добавления в верхнюю часть, которая может быть просто раздута, как и все остальное. Это может выглядеть так:

Образец заголовка

Почему статично ?

Если вам просто нужно отображать текст и изображения, это решение для вас – нет возможности для взаимодействия с пользователем, как кнопки или просмотр пейджеров, поскольку он будет просто нарисован поверх вашего списка.

Управление пустым списком

Если нет изображения для украшения, украшение не будет нарисовано. Вам все равно придется обрабатывать пустой список. (Одним из возможных способов решения проблемы было бы добавление фиктивного элемента в адаптер.)

Код

Вы можете найти полный исходный код здесь, в GitHub, включая Builder чтобы помочь с инициализацией декоратора, или просто использовать приведенный ниже код и предоставить свои собственные значения конструктору.

Не забудьте установить правильный layout_height для вашего представления. Например, match_parent может работать неправильно.

 public class HeaderDecoration extends RecyclerView.ItemDecoration { private final View mView; private final boolean mHorizontal; private final float mParallax; private final float mShadowSize; private final int mColumns; private final Paint mShadowPaint; public HeaderDecoration(View view, boolean scrollsHorizontally, float parallax, float shadowSize, int columns) { mView = view; mHorizontal = scrollsHorizontally; mParallax = parallax; mShadowSize = shadowSize; mColumns = columns; if (mShadowSize > 0) { mShadowPaint = new Paint(); mShadowPaint.setShader(mHorizontal ? new LinearGradient(mShadowSize, 0, 0, 0, new int[]{Color.argb(55, 0, 0, 0), Color.argb(55, 0, 0, 0), Color.argb(3, 0, 0, 0)}, new float[]{0f, .5f, 1f}, Shader.TileMode.CLAMP) : new LinearGradient(0, mShadowSize, 0, 0, new int[]{Color.argb(55, 0, 0, 0), Color.argb(55, 0, 0, 0), Color.argb(3, 0, 0, 0)}, new float[]{0f, .5f, 1f}, Shader.TileMode.CLAMP)); } else { mShadowPaint = null; } } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); // layout basically just gets drawn on the reserved space on top of the first view mView.layout(parent.getLeft(), 0, parent.getRight(), mView.getMeasuredHeight()); for (int i = 0; i < parent.getChildCount(); i++) { View view = parent.getChildAt(i); if (parent.getChildAdapterPosition(view) == 0) { c.save(); if (mHorizontal) { c.clipRect(parent.getLeft(), parent.getTop(), view.getLeft(), parent.getBottom()); final int width = mView.getMeasuredWidth(); final float left = (view.getLeft() - width) * mParallax; c.translate(left, 0); mView.draw(c); if (mShadowSize > 0) { c.translate(view.getLeft() - left - mShadowSize, 0); c.drawRect(parent.getLeft(), parent.getTop(), mShadowSize, parent.getBottom(), mShadowPaint); } } else { c.clipRect(parent.getLeft(), parent.getTop(), parent.getRight(), view.getTop()); final int height = mView.getMeasuredHeight(); final float top = (view.getTop() - height) * mParallax; c.translate(0, top); mView.draw(c); if (mShadowSize > 0) { c.translate(0, view.getTop() - top - mShadowSize); c.drawRect(parent.getLeft(), parent.getTop(), parent.getRight(), mShadowSize, mShadowPaint); } } c.restore(); break; } } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (parent.getChildAdapterPosition(view) < mColumns) { if (mHorizontal) { if (mView.getMeasuredWidth() <= 0) { mView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST)); } outRect.set(mView.getMeasuredWidth(), 0, 0, 0); } else { if (mView.getMeasuredHeight() <= 0) { mView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST)); } outRect.set(0, mView.getMeasuredHeight(), 0, 0); } } else { outRect.setEmpty(); } } } 

Обратите внимание: проект GitHub – это моя персональная площадка. Это не проверено полностью, поэтому библиотеки пока нет .

Что оно делает?

ItemDecoration – дополнительный рисунок к элементу списка. В этом случае украшение рисуется в верхней части первого элемента.

Представление измеряется и выкладывается, затем натягивается на верх первого элемента. Если добавляется эффект параллакса, он также будет привязан к правильным границам.

Вы можете просто разместить свой заголовок и свой RecyclerView в NestedScrollView:

 <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <include layout="@layout/your_header"/> <android.support.v7.widget.RecyclerView android:id="@+id/list_recylclerview" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </android.support.v4.widget.NestedScrollView> 

Чтобы прокрутка работала правильно, вам нужно отключить вложенную прокрутку на вашем RecyclerView:

 myRecyclerView.setNestedScrollingEnabled(false); 

Вы можете добиться этого, используя библиотеку SectionedRecyclerViewAdapter , у нее есть концепция «Разделы», где у Секции есть Заголовок, Нижний колонтитул и Контент (список элементов). В вашем случае вам может понадобиться только один раздел, но у вас может быть много:

Введите описание изображения здесь

1) Создайте собственный класс класса:

 class MySection extends StatelessSection { List<String> myList = Arrays.asList(new String[] {"Item1", "Item2", "Item3" }); public MySection() { // call constructor with layout resources for this Section header, footer and items super(R.layout.section_header, R.layout.section_footer, R.layout.section_item); } @Override public int getContentItemsTotal() { return myList.size(); // number of items of this section } @Override public RecyclerView.ViewHolder getItemViewHolder(View view) { // return a custom instance of ViewHolder for the items of this section return new MyItemViewHolder(view); } @Override public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) { MyItemViewHolder itemHolder = (MyItemViewHolder) holder; // bind your view here itemHolder.tvItem.setText(myList.get(position)); } } 

2) Создайте пользовательский ViewHolder для элементов:

 class MyItemViewHolder extends RecyclerView.ViewHolder { private final TextView tvItem; public MyItemViewHolder(View itemView) { super(itemView); tvItem = (TextView) itemView.findViewById(R.id.tvItem); } } 

3) Настройте свой ReclyclerView с помощью SectionedRecyclerViewAdapter

 // Create an instance of SectionedRecyclerViewAdapter SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter(); MySection mySection = new MySection(); // Add your Sections sectionAdapter.addSection(mySection); // Set up your RecyclerView with the SectionedRecyclerViewAdapter RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setAdapter(sectionAdapter); 

Основываясь на этом сообщении , я создал подкласс RecyclerView.Adapter, который поддерживает произвольное количество верхних и нижних колонтитулов.

https://gist.github.com/mheras/0908873267def75dc746

Хотя это, кажется, решение, я также думаю, что эта вещь должна управляться LayoutManager. К сожалению, мне это нужно сейчас, и у меня нет времени для реализации StaggeredGridLayoutManager с нуля (и даже не от него).

Я все еще проверяю это, но вы можете попробовать, если хотите. Пожалуйста, дайте мне знать, если вы найдете какие-либо проблемы с ним.

У Native API нет такой функции «addHeader», но есть концепция «addItem».

Я смог включить эту специфическую особенность заголовков и расширить для нижнего колонтитула также в моем проекте FlexibleAdapter . Я назвал его прокручиваемыми верхними и нижними колонтитулами .

Вот как они работают:

Прокручиваемые верхние и нижние колонтитулы – это специальные элементы, которые прокручиваются вместе со всеми остальными, но они не относятся к основным элементам (бизнес-элементам), и они всегда обрабатываются адаптером рядом с основными элементами. Эти предметы постоянно расположены на первой и последней позициях.

Введите описание изображения здесь

Есть много о них сказать, лучше прочитать подробную страницу вики .

Кроме того, FlexibleAdapter позволяет создавать заголовки / разделы, а также вы можете иметь их липкие и десятки других функций, таких как расширяемые элементы, бесконечные прокрутки, расширения пользовательского интерфейса и т. Д. … все в одной библиотеке!

Существует еще одно решение, которое охватывает все варианты использования выше: CompoundAdapter: https://github.com/negusoft/CompoundAdapter-android

Вы можете создать AdapterGroup, в которой есть ваш адаптер, как есть, вместе с адаптером с одним элементом для представления заголовка. Код прост и понятен:

 AdapterGroup adapterGroup = new AdapterGroup(); adapterGroup.addAdapter(SingleAdapter.create(R.layout.header)); adapterGroup.addAdapter(new CommentAdapter(...)); recyclerView.setAdapter(adapterGroup); 

AdapterGroup также позволяет вложенность, поэтому для адаптера с разделами вы можете создать AdapterGroup для каждого раздела. Затем поместите все разделы в корневую группу AdapterGroup.

Показ для создания заголовка с элементами в представлении Recycler. Просмотр ресайклера с заголовком

Шаг 1 – Добавьте зависимость в свой файл gradle.

 compile 'com.android.support:recyclerview-v7:23.2.0' // CardView compile 'com.android.support:cardview-v7:23.2.0' 

Cardview используется для украшения.

Шаг2. Сделайте три xml-файла. Один для основной деятельности. Второй для макета заголовка. Третья для макета элемента списка.

activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </RelativeLayout> 

header.xml

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardElevation="2dp"> <TextView android:id="@+id/txtHeader" android:gravity="center" android:textColor="#000000" android:textSize="@dimen/abc_text_size_large_material" android:background="#DCDCDC" android:layout_width="match_parent" android:layout_height="50dp" /> </android.support.v7.widget.CardView> </LinearLayout> 

list.xml

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardElevation="1dp"> <TextView android:id="@+id/txtName" android:text="abc" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.v7.widget.CardView> </LinearLayout> </LinearLayout> 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardElevation="1dp"> <TextView android:id="@+id/txtName" android:text="abc" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.v7.widget.CardView> </LinearLayout> </LinearLayout> 

Шаг 3. Создайте три класса компонентов.

Header.java

 public class Header extends ListItem { private String header; public Header(){} public String getHeader() { return header; } public void setHeader(String header) { this.header = header; } } 

ContentItem.java

 public class ContentItem extends ListItem { private String name; private String rollnumber; @Override public String getName() { return name; } @Override public void setName(String name) { this.name = name; } public String getRollnumber() { return rollnumber; } public void setRollnumber(String rollnumber) { this.rollnumber = rollnumber; } } 

ListItem.java

 public class ListItem { private String name; public ListItem(){} public String getName() { return name; } public void setName(String name) { this.name = name; } private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } 

Шаг 4. Создайте адаптер с именем MyRecyclerAdapter.java

 public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private static final int TYPE_HEADER = 0; private static final int TYPE_ITEM = 1; //Header header; List<ListItem> list; public MyRecyclerAdapter(List<ListItem> headerItems) { this.list = headerItems; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(viewType==TYPE_HEADER) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header, parent, false); return new VHHeader(v); } else { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list, parent, false); return new VHItem(v); } // return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof VHHeader) { // VHHeader VHheader = (VHHeader)holder; Header currentItem = (Header) list.get(position); VHHeader VHheader = (VHHeader)holder; VHheader.txtTitle.setText(currentItem.getHeader()); } else if(holder instanceof VHItem) { ContentItem currentItem = (ContentItem) list.get(position); VHItem VHitem = (VHItem)holder; VHitem.txtName.setText(currentItem.getName()); } } public int getItemViewType(int position) { if(isPositionHeader(position)) return TYPE_HEADER; return TYPE_ITEM; } private boolean isPositionHeader(int position) { return list.get(position) instanceof Header; } @Override public int getItemCount() { return list.size(); } class VHHeader extends RecyclerView.ViewHolder{ TextView txtTitle; public VHHeader(View itemView) { super(itemView); this.txtTitle = (TextView)itemView.findViewById(R.id.txtHeader); } } class VHItem extends RecyclerView.ViewHolder{ TextView txtName; public VHItem(View itemView) { super(itemView); this.txtName = (TextView)itemView.findViewById(R.id.txtName); } } } 

Шаг 5. В MainActivity добавьте следующий код:

 public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; List<List<ListItem>> arraylist; MyRecyclerAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView)findViewById(R.id.my_recycler_view); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); adapter = new MyRecyclerAdapter(getList()); recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setAdapter(adapter); } private ArrayList<ListItem> getList() { ArrayList<ListItem> arrayList=new ArrayList<>(); for(int j=0;j<=4;j++) { Header header=new Header(); header.setHeader("header"+j); arrayList.add(header); for (int i = 0; i <= 3; i++) { ContentItem item = new ContentItem(); item.setRollnumber(i + ""); item.setName("A" + i); arrayList.add(item); } } return arrayList; } } 

Функция getList () динамически генерирует данные для заголовков и элементов списка.

HeaderView зависит от LayoutManager. Ни один из LayoutManagers по умолчанию не поддерживает это и, вероятно, не будет. HeaderView в ListView создает большую сложность без какой-либо существенной выгоды.

Я бы предложил создать класс базового адаптера, который добавляет элементы для заголовков, если они предусмотрены. Не забудьте переопределить методы уведомления, чтобы их правильно компенсировать в зависимости от наличия заголовка или нет.

 First - extends RecyclerView.Adapter<RecyclerView.ViewHolder> public class MenuAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 

After – переопределить метод getItemViewTpe ***.

 @Override public int getItemViewType(int position) { return position; } 

Метод onCreateViewHolder

 @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.menu_item, parent, false); View header = LayoutInflater.from(parent.getContext()).inflate(R.layout.menu_header_item, parent, false); Log.d("onCreateViewHolder", String.valueOf(viewType)); if (viewType == 0) { return new MenuLeftHeaderViewHolder(header, onClickListener); } else { return new MenuLeftViewHolder(view, onClickListener); } } 

Метод onBindViewHolder

 @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (position == 0) { MenuHeaderViewHolder menuHeaderViewHolder = (MenuHeaderViewHolder) holder; menuHeaderViewHolder.mTitle.setText(sMenuTitles[position]); menuHeaderViewHolder.mImage.setImageResource(sMenuImages[position]); } else { MenuViewHolder menuLeftViewHolder = (MenuLeftViewHolder) holder; menuViewHolder.mTitle.setText(sMenuTitles[position]); menuViewHolder.mImage.setImageResource(sMenuImages[position]); } } 

В финише реализует класс ViewHolders static

 public static class MenuViewHolder extends RecyclerView.ViewHolder public static class MenuLeftHeaderViewHolder extends RecyclerView.ViewHolder 

Вероятно, http://alexzh.com/tutorials/multiple-row-layouts-using-recyclerview/ поможет. Он использует только RecyclerView и CardView. Вот адаптер:

 public class DifferentRowAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<CityEvent> mList; public DifferentRowAdapter(List<CityEvent> list) { this.mList = list; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { case CITY_TYPE: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_city, parent, false); return new CityViewHolder(view); case EVENT_TYPE: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_event, parent, false); return new EventViewHolder(view); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { CityEvent object = mList.get(position); if (object != null) { switch (object.getType()) { case CITY_TYPE: ((CityViewHolder) holder).mTitle.setText(object.getName()); break; case EVENT_TYPE: ((EventViewHolder) holder).mTitle.setText(object.getName()); ((EventViewHolder) holder).mDescription.setText(object.getDescription()); break; } } } @Override public int getItemCount() { if (mList == null) return 0; return mList.size(); } @Override public int getItemViewType(int position) { if (mList != null) { CityEvent object = mList.get(position); if (object != null) { return object.getType(); } } return 0; } public static class CityViewHolder extends RecyclerView.ViewHolder { private TextView mTitle; public CityViewHolder(View itemView) { super(itemView); mTitle = (TextView) itemView.findViewById(R.id.titleTextView); } } public static class EventViewHolder extends RecyclerView.ViewHolder { private TextView mTitle; private TextView mDescription; public EventViewHolder(View itemView) { super(itemView); mTitle = (TextView) itemView.findViewById(R.id.titleTextView); mDescription = (TextView) itemView.findViewById(R.id.descriptionTextView); } } } 

И вот сущность:

 public class CityEvent { public static final int CITY_TYPE = 0; public static final int EVENT_TYPE = 1; private String mName; private String mDescription; private int mType; public CityEvent(String name, String description, int type) { this.mName = name; this.mDescription = description; this.mType = type; } public String getName() { return mName; } public void setName(String name) { this.mName = name; } public String getDescription() { return mDescription; } public void setDescription(String description) { this.mDescription = description; } public int getType() { return mType; } public void setType(int type) { this.mType = type; } } 

Здесь кое-что украшение для recycliewiew

 public class HeaderItemDecoration extends RecyclerView.ItemDecoration { private View customView; public HeaderItemDecoration(View view) { this.customView = view; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); customView.layout(parent.getLeft(), 0, parent.getRight(), customView.getMeasuredHeight()); for (int i = 0; i < parent.getChildCount(); i++) { View view = parent.getChildAt(i); if (parent.getChildAdapterPosition(view) == 0) { c.save(); final int height = customView.getMeasuredHeight(); final int top = view.getTop() - height; c.translate(0, top); customView.draw(c); c.restore(); break; } } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (parent.getChildAdapterPosition(view) == 0) { customView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST)); outRect.set(0, customView.getMeasuredHeight(), 0, 0); } else { outRect.setEmpty(); } } } 

Вы можете создать addHeaderView и использовать adapter.addHeaderView (View).

Этот код создает addHeaderView для более одного заголовка. Заголовки должны иметь: android: layout_height = "wrap_content"

 public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int TYPE_ITEM = -1; public class MyViewSHolder extends RecyclerView.ViewHolder { public MyViewSHolder (View view) { super(view); } // put you code. for example: View mView; ... } public class ViewHeader extends RecyclerView.ViewHolder { public ViewHeader(View view) { super(view); } } private List<View> mHeaderViews = new ArrayList<>(); public void addHeaderView(View headerView) { mHeaderViews.add(headerView); } @Override public int getItemCount() { return ... + mHeaderViews.size(); } @Override public int getItemViewType(int position) { if (mHeaderViews.size() > position) { return position; } return TYPE_ITEM; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType != TYPE_ITEM) { //inflate your layout and pass it to view holder return new ViewHeader(mHeaderViews.get(viewType)); } ... } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int basePosition1) { if (holder instanceof ViewHeader) { return; } int basePosition = basePosition1 - mHeaderViews.size(); ... 

}