image


RecyclerView


RecyclerView — это расширенная версия ListView с некоторыми улучшениями в производительности и с новыми функциями. Как следует из названия, RecyclerView перерабатывает или повторно использует представления элементов при прокрутке. В RecyclerView гораздо проще добавлять анимации по сравнению с ListView. В этом уроке мы разберем, как создать RecyclerView с заголовком, футером, разбиением на страницы и анимацией.


Настройка Gradle


Добавьте следующую зависимость в файл build.gradle:


 //пожалуйста, проверьте последнюю версию
 compile 'com.android.support:recyclerview-v7:23.1.1'

Добавление RecyclerView в XML представление


После того, как проект будет синхронизирован, добавьте компонент RecyclerView в ваш макет:


 <android.support.v7.widget.RecyclerView
    android:id="@+id/recycleView"
    android:clipToPadding="false"
    android:padding="8dp"
    android:layout_height="match_parent"
    android:layout_width="match_parent"/>

Привязка XML с классом JAVA


Теперь в методе onCreate вашей активности добавьте следующий код:


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

     // setcontentview и ваше прочий код

        mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);

     // Установите true, если ваш RecyclerView ограничен и имеет фиксированный размер
        mRecyclerView.setHasFixedSize(false);

     // Установите требуемый LayoutManager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

     // Инициализирование и установка адаптера в RecyclerView
        mAdapter = new MyAdapter(mList);
        mRecyclerView.setAdapter(mAdapter);

}

Прежде чем идти дальше, давайте подробно рассмотрим приведенный выше код


  • Layout Manager — Простыми словами, Layout Manager помогает нам определить структуру нашего RecyclerView. Есть три встроенных Layout Managers. Помимо этого, мы можем создать собственный пользовательский Layout Manager, чтобы удовлетворить наши требования.

Виды Layout Manager
  1. LinearLayoutManager показывает элементы в списке с вертикальной или горизонтальной прокруткой.
  2. GridLayoutManager показывает элементы в сетке.
  3. StaggeredGridLayoutManager показывает элементы в шахматной сетке.

  • setHasFixedSize — Установите значение true, если вы не изменяете высоту или ширину у RecyclerView.
  • RecyclerView Adapter — RecyclerView требует адаптер заполнения и управления элементами. Здесь мы передаем ArrayList со значениями в Adapter. Подробное описание адаптера в следующем разделе.

RecyclerView ItemDecoration


ItemDecoration позволяет приложению добавлять специальный полосы и смещения к определенным представлениям элементов из набора данных адаптера. Это может быть полезно для рисования разделителей между элементами, выделениями, границами визуальной группировки и т. д. – developer.android.com

В этом примере мы будем использовать ItemDecoration для добавления отступов к каждому элементу.


public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {
        private int offset;

        public ItemOffsetDecoration(int offset) {
            this.offset = offset;
        }

        @Override
        public void getItemOffsets(Rect outRect, View view,
                                   RecyclerView parent, RecyclerView.State state) {

            // Добавление отступов к нулевому элементу
            if (parent.getChildAdapterPosition(view) == 0) {

                    outRect.right = offset;
                    outRect.left = offset;
                    outRect.top = offset;
                    outRect.bottom = offset;
                }
            }
        }
    }

В вышеприведенном классе мы устанавливаем отступы к нулевому элементу.


 // Внутри onCreate перед установкой адаптера в RecyclerView
 // Здесь мы устанавливаем отступ, равный 20
 mRecyclerView.addItemDecoration(new ItemOffsetDecoration(20));

RecyclerView Adapter


Теперь давайте настроим адаптер ReeyclerView с заголовком и футером.


 public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private static final int TYPE_HEADER = 0;
        private static final int TYPE_ITEM = 1;
        private static final int TYPE_FOOTER = 2;
        ArrayList<String> mList = new ArrayList<>();

        public MyAdapter(ArrayList<String> mList) {
            this.mList = mList;
        }

        @Override
        public int getItemViewType(int position) {
            if (isPositionHeader(position)) {
                return TYPE_HEADER;
            } else if (isPositionFooter(position)) {
                return TYPE_FOOTER;
            }

           return TYPE_ITEM;
        }

       private boolean isPositionHeader(int position) {
            return position == 0;
        }

        private boolean isPositionFooter(int position) {
            return position > mList.size();
        }

         @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

            if (viewType == TYPE_ITEM) {
                View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout, viewGroup, false);
                return new ItemViewHolder(view);

            } else if (viewType == TYPE_HEADER) {
                View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.header_layout, viewGroup, false);
                return new HeaderViewHolder(view);

            } else if (viewType == TYPE_FOOTER) {

                View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.footer_layout,
                        viewGroup, false);
                return new FooterViewHolder(view);

            }

            throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");

        }

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

           if (holder instanceof HeaderViewHolder) {

                //Установите значение из списка в соответствующий компонент пользовательского интерфейса, как показано ниже.
                ((HeaderViewHolder) holder).txtName.setText(mList.get(position))

                //Аналогично можно связывать другие компоненты пользовательского интерфейса

            }else if (holder instanceof ItemViewHolder) {
                 // Ваш код здесь
            }else if (holder instanceof FooterViewHolder) {
                 // Ваш код здесь
            }
        }

        @Override
        public int getItemCount() {
            // Увеличьте на два для размещения заголовка и подвала
            return this.mList.size() + 2;
        }

      // ViewHolders для заголовка, элемента и подвала
        class HeaderViewHolder extends RecyclerView.ViewHolder {
            public View View;
            private final TextView txtName;

            public HeaderViewHolder(View itemView) {
                super(itemView);
                View = itemView;

            // Добавьте свои компоненты ui здесь, как показано ниже
            txtName = (TextView) View.findViewById(R.id.txt_name);

            }
        }

        public class ItemViewHolder extends RecyclerView.ViewHolder {
            public View View;
            public ViewHolder(View v) {
                super(v);
                View = v;
                // Добавьте компоненты пользовательского интерфейса здесь.
            }
        }

        public class FooterViewHolder extends RecyclerView.ViewHolder {
            public View View;
            public ViewHolder(View v) {
                super(v);
                View = v;
                // Добавьте компоненты пользовательского интерфейса здесь.
            }
        }
    }

Пагинация


Теперь, когда адаптер готов, давайте посмотрим, как добавить пагинацию в список RecyclerView. Это довольно легко сделать и должно быть добавлено в onCreate после установки Adapter to Recycler-View.


 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                int lastvisibleitemposition = mLayoutManager.findLastVisibleItemPosition();

                if (lastvisibleitemposition == mAdapter.getItemCount() - 1) {

                    if (!loading && !isLastPage) {

                        loading = true;
                        fetchData((++pageCount));
                        // Увеличиваем на 1 pagecount при каждой прокрутке для получения данных со следующей страницы
                        // make loading = false после загрузки данных
                        // Вызовите mAdapter.notifyDataSetChanged (), чтобы обновить адаптер и макет
                    }
                }
            }
        });

Всякий раз, когда данные изменяются в mList, вызывайте функцию ниже, чтобы обновить адаптер RecyclerView и показать новые данные.


mAdapter.notifyDataSetChanged();

Надеюсь, что этот пост поможет вам получить общее представление о настройке RecyclerView с заголовком, подвалом и пагинацией.

Комментарии (5)


  1. Demon_i
    23.08.2017 01:19
    +1

    Так все таки «с заголовком, футером и пагинацией», «с заголовком, футером, разбиением на страницы и анимацией» или «с заголовком, подвалом и пагинацией»? Почему бы не писать все на одном языке без коверканных англицизмов, тем более, что Вы знаете перевод и используете его по тексту?


  1. FireWoolf
    23.08.2017 11:24

    setHasFixedSize — Установите значение true, вы не изменяете высоту или ширину у RecyclerView

    А точно это относится именно к RecyclerView? Или может к его элементам?


    1. velkonost Автор
      23.08.2017 11:32

      Если размер RecyclerView (самого RecyclerView) ...


      не зависит от содержимого адаптера:


      mRecyclerView.setHasFixedSize(true);

      зависит от содержимого адаптера:


      mRecyclerView.setHasFixedSize(false);

      Установка true не означает, что размер RecyclerView фиксирован, это просто означает, что он не изменится из-за изменения содержимого адаптера.


      Также, можете ознакомиться с этим методом в RecyclerView.java


      1. FireWoolf
        23.08.2017 14:59

        Понял, Спасибо!


  1. demonit
    24.08.2017 07:05

    статья — мусор. Нет ни одного скрина, нет толком описание метода огранизации футера, навигации… нет в конце концов той самой пагинации (действительно, только от одного слова коробит). Постраничная навигация предусматривает некоторые управляющие элементы, позволяющие ее организовать. Где они здесь?
    К переводчикам, конечно, претензии не относятся, за исключением — зачем переводить мусор?
    PS: да, и, наконец, нет демо-проекта где все это можно пробовать…