Skip to content
Related Articles

Related Articles

Improve Article

How to Create a Collapsing ToolBar and FAB on Scroll with RecyclerView in Android?

  • Last Updated : 18 Jul, 2021

In this article, we are going to create a collapsing Toolbar and Floating action button (FAB) on scroll with RecyclerView. Many popular apps have this effect eg. LinkedIn. Below is the sample video to show what we are going to build. Note that we are going to implement this project using the Kotlin language. 

Step by Step Implementation

Step 1: Create a new project

Want a more fast-paced & competitive environment to learn the fundamentals of Android?
Click here to head to a guide uniquely curated by our experts with the aim to make you industry ready in no time!

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.

Step 2: Add view binding dependency



Go to build.gradle(app) and the following dependency inside the android tag and click sync now.

buildFeatures {

     viewBinding true

 }

Step 3: Working with the activity_main.xml file

Go to the activity_main.xml file and refer to the following code. Below is the code for the activity_main.xml file. Comments are added inside the code to understand the code in more detail.

XML




<?xml version="1.0" encoding="utf-8"?>
<!--first of all you have to change
    the layout as CoordinatorLayout.-->
<androidx.coordinatorlayout.widget.CoordinatorLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <!--First child of CoordinatorLayout layout
         should be App Bar Layout-->
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
  
        <!-- Add Material toolbar make the layout_scrollFlags
              to scroll|enterAlways (Important)-->
        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways"
            app:title="@string/app_name" />
  
    </com.google.android.material.appbar.AppBarLayout>
  
    <!--Add a recycler view
        inside layout behaviour add "@string/appbar_scrolling_view_behavior" (Important)
        by default it comes from the @string-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#F5F8FD"
        android:orientation="vertical"
        android:padding="5dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
  
    <!--Add a floating action button
        "com.google.android.material.behavior.HideBottomViewOnScrollBehavior" (Important)-->
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:layout_margin="16dp"
        android:src="@drawable/ic_baseline_add_24"
        app:fabSize="normal"
        app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
        app:tint="@android:color/white" />
  
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Step 4: Create a new layout file and name it a single_item.xml file



Go to the single_item.xml file and refer to the following code. Below is the code for the single_item.xml file. It is the single item layout that we will use in RecyclerView.

XML




<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
    android:layout_width="match_parent"
    android:layout_marginBottom="10dp"
    android:layout_marginStart="5dp"
    android:layout_marginEnd="5dp"
    android:layout_height="110dp">
  
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
  
        <!--Add image view, We will not set any data here.-->
        <ImageView
            android:id="@+id/iv_language"
            android:layout_width="80dp"
            android:layout_height="90dp"
            android:layout_marginStart="20dp"
            android:layout_marginTop="10dp"
            android:scaleType="fitCenter"
            android:src="@mipmap/ic_launcher"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
  
        <!--Text view for showing the language name-->
        <TextView
            android:id="@+id/tv_lang_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="30dp"
            android:layout_marginTop="30dp"
            android:text="Language"
            android:textSize="16sp"
            android:textStyle="bold"
            app:layout_constraintLeft_toRightOf="@id/iv_language"
            app:layout_constraintTop_toTopOf="parent" />
  
        <!--Text View for showing the exp-->
        <TextView
            android:id="@+id/tv_exp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="Exp : 3 years"
            app:layout_constraintLeft_toLeftOf="@id/tv_lang_name"
            app:layout_constraintTop_toBottomOf="@id/tv_lang_name" />
  
    </androidx.constraintlayout.widget.ConstraintLayout>
  
</com.google.android.material.card.MaterialCardView>

Step 5: Create a new model class

Create a new class Language.kt we will use data of custom generic “Language” to pass in the list that will be shown in recycler view.

Kotlin




// this is the Language model class
class Language(
    val name : String ="",
    val exp : String = ""
)

Step 6: Working with the adapter class

Create a new class RvAdapter.kt this will act as an Adapter class for the recycler view. Comments are added before the code for better understanding.

Kotlin




import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.introidx.collapsingtoolbargfg.databinding.SingleItemBinding
  
class RvAdapter(
    private var languageList: List<Language>) : RecyclerView.Adapter<RvAdapter.ViewHolder>() {
  
    // create an inner class with name ViewHolder
    // It takes a view argument, in which pass the 
    // generated class of single_item.xml
    // ie SingleItemBinding and in the 
    // RecyclerView.ViewHolder(binding.root) pass it like this
    inner class ViewHolder(val binding: SingleItemBinding) : RecyclerView.ViewHolder(binding.root)
  
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = SingleItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }
  
    // bind the items with each item of 
    // the list languageList which than will be
    // shown in recycler view
    // to keep it simple we are not 
    // setting any image data to view
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        with(holder) {
            with(languageList[position]) {
                // set text to language name
                binding.tvLangName.text = this.name
                // set exp
                binding.tvExp.text = this.exp
            }
        }
    }
  
    // return the size of languageList
    override fun getItemCount(): Int {
        return languageList.size
    }
}

Step 7: Working with MainActivity.kt

Go to the MainActivity.kt file and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.

Kotlin




import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.introidx.collapsingtoolbargfg.databinding.ActivityMainBinding
  
class MainActivity : AppCompatActivity() {
  
    // view binding for the activity
    private var _binding: ActivityMainBinding? = null
    private val binding get() = _binding!!
  
    // get reference to the adapter class
    private var languageList = ArrayList<Language>()
    private lateinit var rvAdapter: RvAdapter
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
  
        // define layout manager for the Recycler view
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
          
        // attach adapter to the recycler view and also handle item click
  
        // attach adapter to the recycler view
        rvAdapter = RvAdapter(languageList)
  
        // add adapter to the recycler view
        binding.recyclerView.adapter = rvAdapter
  
        // create objects of Language
        // create some row data
        val language1 = Language("Java", "3 Year exp")
        val language2 = Language("Kotlin", "2 Year exp")
        val language3 = Language("Python", "1 Year exp")
        val language4 = Language("CPP", "5 Year exp")
        val language5 = Language("PHP", "No exp")
  
        // pass raw data t rhe list
        languageList.add(language1)
        languageList.add(language2)
        languageList.add(language3)
        languageList.add(language4)
        languageList.add(language5)
        languageList.add(language3)
        languageList.add(language4)
        languageList.add(language5)
        languageList.add(language3)
        languageList.add(language4)
        languageList.add(language5)
  
        rvAdapter.notifyDataSetChanged()
  
    }
  
    // on destroy of view make the 
      // binding reference to null
    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}

Output:




My Personal Notes arrow_drop_up
Recommended Articles
Page :