Эффект заголовка Parallax с RecyclerView

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

Обычно со списком ListView я устанавливаю пустой заголовок в заголовке и помещаю изображение под списком и переводит нижнее изображение с прокруткой списка, чтобы создать эффект Parallax.

Итак, без заголовка, как я могу создать тот же эффект параллакса с помощью RecyclerView?

Ответ 1

Итак, сегодня я попытался архивировать этот эффект на RecyclerView. Я смог это сделать, но поскольку код слишком много, я вставлю сюда свой проект github, и я объясню некоторые ключевые моменты проекта.

https://github.com/kanytu/android-parallax-recyclerview

Сначала нам нужно посмотреть getItemViewType на класс RecyclerView.Adapter. Эти методы определяют, с каким видом мы имеем дело. Этот тип будет передан на onCreateViewHolder, и мы сможем раздуть разные виды. Так что я сделал: проверьте, является ли позиция первой. Если это так, раздуйте заголовок, если не надуть нормальную строку.

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

С этого момента вы, кажется, знаете остальную логику, стоящую за ней.

Конечный результат:

enter image description here

EDIT:

Если вам нужно вставить что-то в адаптер, обязательно сообщите правильную позицию, добавив 1 в метод notifyItemChanged/Inserted. Например:

public void addItem(String item, int position) {
    mData.add(position, item);
    notifyItemInserted(position + 1); //we have to add 1 to the notification position since we don't want to mess with the header
}

Другим важным изменением, которое я сделал, является логика прокрутки. Система mCurrentOffset, которую я использовал, не работала с вставкой элемента, поскольку смещение изменится, если вы добавите элемент. Так что я сделал:

ViewHolder holder = findViewHolderForPosition(0);
if (holder != null)
  ((ParallaxRecyclerAdapter) getAdapter()).translateHeader(-holder.itemView.getTop() * 0.5f);

Чтобы проверить это, я добавил postDelayed Runnable, запустил приложение, прокручивал до конца, добавлял элемент в позицию 0 и снова прокручивал вверх. В результате получилось:

enter image description here

Если кто-то ищет другие эффекты параллакса, они могут проверить мое другое репо:

https://github.com/kanytu/android-parallax-listview

Ответ 2

Самый простой способ сделать это, используя ниже onScrollListener, не полагаясь на какую-либо библиотеку.

View view = recyclerView.getChildAt(0);
if(view != null && recyclerView.getChildAdapterPosition(view) == 0)  {
     view.setTranslationY(-view.getTop() / 2);// or use view.animate().translateY();
}

убедитесь, что ваш второй элемент viewHolder имеет цвет фона, соответствующий фону ящика/активности. поэтому прокрутка выглядит параллаксом.

Ответ 3

Этот ответ для тех, кто интересуется добавлением заголовка параллакса в GridLayoutManager или StaggeredGridLayoutManager

Вам нужно добавить следующий код к вашему адаптеру в onBindViewHolder или onCreateViewHolder

StaggeredGridLayoutManager.LayoutParams layoutParams =
                    (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            layoutParams.setFullSpan(true);

Ответ 4

Для kotlin вы можете настроить вид ресайклера ниже

//setting parallax effects
    recyclerView.addOnScrollListener(object :RecyclerView.OnScrollListener(){
        override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)
            val view = recyclerView?.getChildAt(0)
            if (view != null && recyclerView?.getChildAdapterPosition(view) === 0) {
                val imageView = view.findViewById(R.id.parallaxImage)
                imageView.translationY = -view.top / 2f
            }
        }
    })