Shimmer Effect RecyclerView Android Kotlin
This article explains how you can use shimmer effect for recyclerview while data is loading from server in android applications using kotlin language. This type of progress view is displayed in facebook mobile app.
Facebook created this shimmer library to display some progress view with an animation when data is loading. Normally we use simple progressbar while data is fetching from api in our android apps. In this example, we are using this shimmer library to display shimmer effect placeholder.
We are using retrofit library to fetch data from api and display it in recyclerview. Shimmer library provides ShimmerFrameLayout which is used to display shimmer effect. We need to just simply nest any layout into this ShimmerFrameLayout to implement shimmer effect.
Add required dependencies in your app level build.gradle file
implementation ‘com.facebook.shimmer:shimmer:0.1.0@aar’
// retrofit library
implementation ‘com.squareup.retrofit2:retrofit:2.5.0’
implementation ‘com.squareup.retrofit2:converter-gson:2.5.0’
implementation ‘com.squareup.okhttp3:logging-interceptor:3.9.1’
// ui
implementation ‘com.android.support:recyclerview-v7:28.1.1’
implementation ‘com.android.support:cardview-v7:28.1.1’
Adapter Row Layout For RecyclerView Android Kotlin
<androidx.cardview.widget.CardView xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
app:cardCornerRadius=”10dp”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”8dp”
android:layout_marginBottom=”8dp”
android:layout_marginStart=”15dp”
android:layout_marginEnd=”15dp”>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:padding=”10dp”>
<TextView
android:id=”@+id/txt_user_name”
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toTopOf=”parent”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textSize=”22sp”
android:textStyle=”bold” />
<TextView
android:id=”@+id/txt_user_info1″
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toBottomOf=”@+id/txt_user_name”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textSize=”16sp” />
<TextView
android:id=”@+id/txt_user_info2″
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toBottomOf=”@+id/txt_user_info1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textSize=”16sp” />
<TextView
android:id=”@+id/txt_shimmer_user_address”
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toBottomOf=”@+id/txt_user_info2″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textSize=”16sp” />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Shimmer Effect Layout
We need to create same layout as adapter row layout. We just need to add background color grey or non white for shimmer effect. Shimmer effect is not possible without without this background color.
<androidx.cardview.widget.CardView 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=”wrap_content”
android:layout_marginStart=”15dp”
android:layout_marginTop=”8dp”
android:layout_marginEnd=”15dp”
android:layout_marginBottom=”8dp”
app:cardCornerRadius=”10dp”>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:padding=”10dp”>
<TextView
android:id=”@+id/txt_shimmer_user_name”
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:background=”#dddddd”
android:textSize=”22sp”
android:textStyle=”bold”
app:layout_constraintEnd_toEndOf=”parent”
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toTopOf=”parent” />
<TextView
android:id=”@+id/txt_shimmer_user_info1″
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:layout_marginTop=”5dp”
android:background=”#dddddd”
android:textSize=”16sp”
app:layout_constraintEnd_toEndOf=”parent”
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toBottomOf=”@+id/txt_shimmer_user_name” />
<TextView
android:id=”@+id/txt_shimmer_user_info2″
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:layout_marginTop=”5dp”
android:background=”#dddddd”
android:textSize=”16sp”
app:layout_constraintEnd_toEndOf=”parent”
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toBottomOf=”@+id/txt_shimmer_user_info1″ />
<TextView
android:id=”@+id/txt_shimmer_user_address”
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:layout_marginTop=”5dp”
android:background=”#dddddd”
android:textSize=”16sp”
app:layout_constraintEnd_toEndOf=”parent”
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toBottomOf=”@+id/txt_shimmer_user_info2″ />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Create Api Response Classes
@SerializedName(“id”)
val userId: Int? = null,
@SerializedName(“name”)
val name: String? = null,
@SerializedName(“username”)
val userName: String? = null,
@SerializedName(“email”)
val userEmail: String? = null,
@SerializedName(“address”)
val userAddressObject : Address? = null,
@SerializedName(“phone”)
val userPhone: String? = null,
@SerializedName(“website”)
val userWebsite: String? = null
) : Serializable
@SerializedName(“street”)
val streetAddress: String? = null,
@SerializedName(“suite”)
val suiteAddress: String? = null,
@SerializedName(“city”)
val cityAddress: String? = null,
@SerializedName(“zipcode”)
val zipCodeAddress: String? = null
) : Serializable
Create Adapter For RecyclerView Android Kotlin
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val inflater = LayoutInflater.from(context)
val view: View = inflater.inflate(R.layout.layout_user_row,parent,false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return usersList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val getUser = usersList[position]
holder.userName?.text = getUser.name
holder.userInfo1?.text = getUser?.userName + ” | ” + getUser?.userEmail
holder.userInfo2?.text = getUser?.userPhone + ” | ” + getUser?.userWebsite
val userAddressObj = getUser.userAddressObject
holder.userAddress?.text = userAddressObj?.suiteAddress + “,” + userAddressObj?.streetAddress + “,” + userAddressObj?.cityAddress + “,” + userAddressObj?.zipCodeAddress
}
class MyViewHolder(var view: View) : RecyclerView.ViewHolder(view){
var userName: TextView? = null
var userInfo1: TextView? = null
var userInfo2: TextView? = null
var userAddress: TextView? = null
init {
userName = view.findViewById(R.id.txt_shimmer_user_name)
userInfo1 = view.findViewById(R.id.txt_shimmer_user_info1)
userInfo2 = view.findViewById(R.id.txt_shimmer_user_info2)
userAddress = view.findViewById(R.id.txt_shimmer_user_address)
}
}
}
RecyclerView Layout
In this main layout, we need to add ShimmerFrameLayout. In ShimmerFrameLayout, We need to add multiple times placeholder layouts for shimmer effect.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<com.facebook.shimmer.ShimmerFrameLayout
android:id=”@+id/shimmer_frame_main”
android:layout_width=”0dp”
android:layout_height=”0dp”
android:layout_gravity=”center”
app:layout_constraintBottom_toBottomOf=”parent”
app:layout_constraintLeft_toLeftOf=”parent”
app:layout_constraintRight_toRightOf=”parent”
app:layout_constraintTop_toTopOf=”parent”
android:orientation=”vertical”>
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical”>
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
<include layout=”@layout/layout_shimmer_placeholder” />
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id=”@+id/recycler_view_main”
android:layout_width=”0dp”
android:layout_height=”0dp”
app:layout_constraintBottom_toBottomOf=”parent”
app:layout_constraintLeft_toLeftOf=”parent”
app:layout_constraintRight_toRightOf=”parent”
app:layout_constraintTop_toTopOf=”parent”
android:visibility=”gone”/>
</androidx.constraintlayout.widget.ConstraintLayout>
Start Shimmer Effect For RecyclerView Android Kotlin
First we start shimmer effect whenever we call api to fetch data. After getting response from api then we stop shimmer effect and make recyclerview visible.
private var usersList: MutableList<User> = mutableListOf<User>()
private var usersAdapter: UsersAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
usersList = mutableListOf()
recycler_view_main.layoutManager = LinearLayoutManager(this@MainActivity)
usersAdapter = UsersAdapter(this, usersList)
recycler_view_main.adapter = usersAdapter
if (isInternetAvailable()) {
getUsersData()
}
}
private fun getUsersData() {
ApiClient.apiService.getUsers().enqueue(object : Callback<MutableList<User>> {
override fun onFailure(call: Call<MutableList<User>>, t: Throwable) {
shimmer_frame_main.stopShimmerAnimation()
shimmer_frame_main.visibility = View.GONE
Log.e(“error”, t.localizedMessage)
}
override fun onResponse(
call: Call<MutableList<User>>,
response: Response<MutableList<User>>
) {
shimmer_frame_main.stopShimmerAnimation()
shimmer_frame_main.visibility = View.GONE
recycler_view_main.visibility = View.VISIBLE
val usersResponse = response.body()
usersList.clear()
usersResponse?.let { usersList.addAll(it) }
usersAdapter?.notifyDataSetChanged()
}
})
}
override fun onResume() {
super.onResume()
shimmer_frame_main.startShimmerAnimation()
}
override fun onPause() {
shimmer_frame_main.stopShimmerAnimation()
super.onPause()
}
}


Pingback: Shimmer Effect ListView Flutter - CodingWithDhrumil