Open In App

Auto-Hide or Auto-Extend Floating Action Button in RecyclerView in Android

Improve
Improve
Like Article
Like
Save
Share
Report

In the article Auto-Hide or Auto-Extend Floating Action Button for NestedScrollView in Android it’s been discussed and demonstrated how to auto-extend or hide the Floating Action Button in the Nested Scroll View. In this article, it’s discussed how to Hide or Extend the Floating Action Button in Android. Look at the following image to get an overview of the discussion.

Auto-Hide or Auto-Extend Floating Action Button in RecyclerView in Android

Create an empty activity project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.

Add Required Dependency

Include google material design components dependency in the build.gradle file. After adding the dependencies don’t forget to click on the “Sync Now” button present at the top right corner.

implementation “androidx.recyclerview:recyclerview:1.2.1”

Note that while syncing your project you need to be connected to the network and make sure that you are adding the dependency to the app-level Gradle file as shown below.

Steps to Hide or Extend FAB when scrolled in RecyclerView

Step 1: Working with activity_main.xml file

The main layout of the project contains one RecyclerView and one Normal Floating Action Button. To implement the same layout invoke the following code inside the activity_main.xml file.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/normalFAB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_add"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
  
</androidx.constraintlayout.widget.ConstraintLayout>


Before going to the output we need to populate the RecyclerView with the data. So we need to now work with RecyclerView Adapter and a custom view for the RecyclerView.

Step 2: Create a custom view for RecyclerView

The custom view for the RecyclerView contains one simple icon at the left and two TextViews. To implement the same create a file named recycler_data_view.xml inside the layout folder and invoke the following code.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp">
  
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="54dp"
        android:layout_height="54dp"
        android:src="@drawable/ic_android"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
  
    <TextView
        android:id="@+id/tvNumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/tvNumbersInText"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="1" />
  
    <TextView
        android:id="@+id/tvNumbersInText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="@+id/tvNumber"
        app:layout_constraintTop_toBottomOf="@+id/tvNumber"
        tools:text="One" />
  
</androidx.constraintlayout.widget.ConstraintLayout>


The above custom view produces the following output for each item in the list:

Step 3: Creating Data Class for RecyclerView

Now creating the data for the above custom view by creating a Data Class, using the following code.

Kotlin




data class RecyclerViewData(
    val text1: String,
    val text2: String
)


Step 4: Creating the RecyclerView Adapter

The following code needs to invoke in a separate class by creating the class named as MyRecyclerAdapter.

Kotlin




import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
  
class MyRecyclerViewAdapter(private val items: List<RecyclerViewData>) :
    RecyclerView.Adapter<MyRecyclerViewAdapter.MyRecyclerViewDataHolder>() {
  
    inner class MyRecyclerViewDataHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
  
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecyclerViewDataHolder {
        val view: View =
            LayoutInflater.from(parent.context).inflate(R.layout.recycler_data_view, parent, false)
        return MyRecyclerViewDataHolder(view)
    }
  
    override fun onBindViewHolder(holder: MyRecyclerViewDataHolder, position: Int) {
        val currentItem: RecyclerViewData = items[position]
  
        val tvNumber: TextView = holder.itemView.findViewById(R.id.tvNumber)
        tvNumber.text = currentItem.text1
  
        val tvNumbersInText: TextView = holder.itemView.findViewById(R.id.tvNumbersInText)
        tvNumbersInText.text = currentItem.text2
    }
  
    override fun getItemCount(): Int {
        return items.size
    }
}


Step 5: Working with the MainActivity.kt file

In this class, we have to create some sample data for the RecyclervView in the form of a list and handle the scroll listener for the recycler view when it is scrolled up and down. When it scrolled up we have to hide the FAB and show the FAB when scrolled down. To implement the same invoke the following code inside the MainActivity.kt file (comments are added for better understanding).

Kotlin




import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
  
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        // create an instance of the Normal Floating Action Button
        // and register with the appropriate ID
        val fab: FloatingActionButton = findViewById(R.id.normalFAB)
  
        // create instance of RecyclerView and 
        // register with the appropriate ID
        val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
  
        // create list of RecyclerViewData
        var recyclerViewData = listOf<RecyclerViewData>()
        recyclerViewData = recyclerViewData + RecyclerViewData("1", "One")
        recyclerViewData = recyclerViewData + RecyclerViewData("2", "Two")
        recyclerViewData = recyclerViewData + RecyclerViewData("3", "Three")
        recyclerViewData = recyclerViewData + RecyclerViewData("4", "Four")
        recyclerViewData = recyclerViewData + RecyclerViewData("5", "Five")
        recyclerViewData = recyclerViewData + RecyclerViewData("6", "Six")
        recyclerViewData = recyclerViewData + RecyclerViewData("7", "Seven")
        recyclerViewData = recyclerViewData + RecyclerViewData("8", "Eight")
        recyclerViewData = recyclerViewData + RecyclerViewData("9", "Nine")
        recyclerViewData = recyclerViewData + RecyclerViewData("10", "Ten")
        recyclerViewData = recyclerViewData + RecyclerViewData("11", "Eleven")
        recyclerViewData = recyclerViewData + RecyclerViewData("12", "Twelve")
        recyclerViewData = recyclerViewData + RecyclerViewData("13", "Thirteen")
        recyclerViewData = recyclerViewData + RecyclerViewData("14", "Fourteen")
        recyclerViewData = recyclerViewData + RecyclerViewData("15", "Fifteen")
  
        // create a vertical layout manager
        val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
  
        // create instance of MyRecyclerViewAdapter
        val myRecyclerViewAdapter = MyRecyclerViewAdapter(recyclerViewData)
  
        // attach the adapter to the recycler view
        recyclerView.adapter = myRecyclerViewAdapter
  
        // also attach the layout manager
        recyclerView.layoutManager = layoutManager
  
        // make the adapter the data set changed for the recycler view
        myRecyclerViewAdapter.notifyDataSetChanged()
  
        // now creating the scroll listener for the recycler view
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
  
                // if the recycler view is scrolled
                // above hide the FAB
                if (dy > 10 && fab.isShown) {
                    fab.hide()
                }
  
                // if the recycler view is 
                // scrolled above show the FAB
                if (dy < -10 && !fab.isShown) {
                    fab.show()
                }
  
                // of the recycler view is at the first
                // item always show the FAB
                if (!recyclerView.canScrollVertically(-1)) {
                    fab.show()
                }
            }
        })
    }
}


Output:

For Extended Floating Action Button

Make changes to the activity_main.xml file by invoking the following code.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  
    <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
        android:id="@+id/extendedFAB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="ADD ITEM"
        app:icon="@drawable/ic_add"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
  
</androidx.constraintlayout.widget.ConstraintLayout>


Make changes inside the MainActivity.kt file by invoking the following code.

Kotlin




import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
  
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        // create an instance of the Normal Floating Action Button
        // and register with the appropriate ID
        val fab: ExtendedFloatingActionButton = findViewById(R.id.extendedFAB)
  
        // create instance of RecyclerView and register with the appropriate ID
        val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
  
        // create list of RecyclerViewData
        var recyclerViewData = listOf<RecyclerViewData>()
        recyclerViewData = recyclerViewData + RecyclerViewData("1", "One")
        recyclerViewData = recyclerViewData + RecyclerViewData("2", "Two")
        recyclerViewData = recyclerViewData + RecyclerViewData("3", "Three")
        recyclerViewData = recyclerViewData + RecyclerViewData("4", "Four")
        recyclerViewData = recyclerViewData + RecyclerViewData("5", "Five")
        recyclerViewData = recyclerViewData + RecyclerViewData("6", "Six")
        recyclerViewData = recyclerViewData + RecyclerViewData("7", "Seven")
        recyclerViewData = recyclerViewData + RecyclerViewData("8", "Eight")
        recyclerViewData = recyclerViewData + RecyclerViewData("9", "Nine")
        recyclerViewData = recyclerViewData + RecyclerViewData("10", "Ten")
        recyclerViewData = recyclerViewData + RecyclerViewData("11", "Eleven")
        recyclerViewData = recyclerViewData + RecyclerViewData("12", "Twelve")
        recyclerViewData = recyclerViewData + RecyclerViewData("13", "Thirteen")
        recyclerViewData = recyclerViewData + RecyclerViewData("14", "Fourteen")
        recyclerViewData = recyclerViewData + RecyclerViewData("15", "Fifteen")
  
        // create a vertical layout manager
        val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
  
        // create instance of MyRecyclerViewAdapter
        val myRecyclerViewAdapter = MyRecyclerViewAdapter(recyclerViewData)
  
        // attach the adapter to the recycler view
        recyclerView.adapter = myRecyclerViewAdapter
  
        // also attach the layout manager
        recyclerView.layoutManager = layoutManager
  
        // make the adapter the data set
        // changed for the recycler view
        myRecyclerViewAdapter.notifyDataSetChanged()
  
        // now creating the scroll listener
        // for the recycler view
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
  
                // if the recycler view is scrolled 
                // above shrink the FAB
                if (dy > 10 && fab.isExtended) {
                    fab.shrink()
                }
  
                // if the recycler view is scrolled
                // above extend the FAB
                if (dy < -10 && !fab.isExtended) {
                    fab.extend()
                }
  
                // of the recycler view is at the first
                // item always extend the FAB
                if (!recyclerView.canScrollVertically(-1)) {
                    fab.extend()
                }
            }
        })
    }
}


Output:



Last Updated : 27 Sep, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads