Soheil
Soheil

Reputation: 627

android-add moving header above RecyclerView

I need to add a header above the RecyclerView in my app. the header must move as the user scrolls the recyclerview (right figure). I have already searched but have not found a final straightforward solution. what is the best and easiest way to implement it?

enter image description here

image credit: link

Upvotes: 1

Views: 1505

Answers (1)

lterminiello
lterminiello

Reputation: 56

For this you have 2 alternatives.

  1. The first and simplest, you can add an ImageView in a CollapsingToolbarLayout inside a CoordinatorLayout and then add app:layout_behavior="@string/appbar_scrolling_view_behavior" to your RecyclerView

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content>

            <com.google.android.material.appbar.CollapsingToolbarLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">

                    <ImageView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"/>

                    <androidx.appcompat.widget.Toolbar
                        android:layout_width="match_parent"
                        android:layout_height="?actionBarSize"
                        app:layout_collapseMode="pin"/>

            </com.google.android.material.appbar.CollapsingToolbarLayout>

        </com.google.android.material.appbar.AppBarLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/transparent"
            android:fillViewport="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

</androidx.coordinatorlayout.widget.CoordinatorLayout>
  1. The second option which will have the same effect when scrolling, is that in your ReyclerViewAdapter it understands 2 viewTypes, one for the image and the other for the items, in this way you must pass the image as the first item of your item list
class CustomAdapter(
            private var list: ArrayList<String>
    ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {


        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return if (viewType == VIEW_TYPE_ONE) {
                ViewHolder1(LayoutInflater.from(context).inflate(R.layout.your_list_item_1, parent, false))
            } else ViewHolder2(LayoutInflater.from(context).inflate(R.layout.your_list_item_2, parent, false))
        }

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            if (position == 0) {
                (holder as ViewHolder1).bind(position)
            } else {
                (holder as ViewHolder2).bind(position)
            }
        }

        override fun getItemCount(): Int {
            return list.size
        }

        override fun getItemViewType(position: Int): Int {
            return if (position == 0) {
                VIEW_TYPE_ONE
            } else VIEW_TYPE_TWO
        }


        private inner class ViewHolder1 internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {

            var yourView: ImageView  = itemView.findViewById(R.id.yourView)

            fun bind(position: Int) {
                yourView.setImageResource(list[position])
            }
        }

        private inner class ViewHolder2 internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {

            var yourView: TextView = itemView.findViewById(R.id.yourView)

            fun bind(position: Int) {
                yourView.text = list[position]
            }
        }

        companion object {
            private const val VIEW_TYPE_ONE = 1
            private const val VIEW_TYPE_TWO = 2
        }

Upvotes: 4

Related Questions