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

// shimmer library
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

<?xml version=”1.0″ encoding=”utf-8″?>
<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.

<?xml version=”1.0″ encoding=”utf-8″?>
<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

data class User(
@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

 
data class Address(

@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

class UsersAdapter(private val context: Context, private var usersList: MutableList<User>) : RecyclerView.Adapter<UsersAdapter.MyViewHolder>() {

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.

<?xml version=”1.0″ encoding=”utf-8″?>
<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.

class MainActivity : AppCompatActivity() {

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()
}

}

 
 
 
recyclerview android kotlin
 

Leave a Reply