Auto-Hide or Auto-Extend Floating Action Button in RecyclerView in Android
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.
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 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 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 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:
Please Login to comment...