Dauris Little

  • About
  • Dauris’s Portfolio
  • Blogging Lyf
  • Contact

Shimmering in Android

Avatar photo
Dauris
Saturday, 15 August 2020 / Published in Android, Kotlin, Programming Languages

Shimmering in Android

You may or may not  have been aware of certain UX effects within the Facebook application that fires when attempting to retrieve a large amount of data from the network. This library was created by the developers over at Facebook so big shout out to their developer team. This library serves to provide an alternative method of notifying the user that data is being retrieved rather than using the old traditional ProgressBar. There is no surprise that later on Facebook released an open-source library called shimmer which any developer can now implement the shimmer effect.

In this article, we are demonstrating how to execute the shimmer in any android application. We are going to attempt to fetch data from the API using the dependency Fast Android Networking and then display the data in the recycler view. So let’s get to what you’re interested in the code.

Begining the Application

So fire up the Android Studio and create a new project:

  • Select Empty Acivity and select next
    • Name: Application Name
    • Package Name: com.programmingninja.applicationame
    • Language: Kotlin
    • Minimum SDK: API 19
    • “FINISH”

Adding ‘Dependencies’

Add the following dependencies in your app level build.gradle and sync

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha05'
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    //adding dependencies
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    implementation 'com.facebook.shimmer:shimmer:0.5.0@aar'
    implementation 'com.amitshekhar.android:android-networking:1.0.2'
    implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha05'
}

Within the ‘values’ folder need to add the color code to use in the application. Note adding this background color should be grey or any non-white color since the shimmering effect won’t be visible if you are using a white background. 

<color name="colorGrey">#dddddd</color>

Find the AndroidManifest file and add the following permission within the <manifest></manifest> block

<uses-permission android:name="android.permission.INTERNET" />

To give you some background on the dependencies we add the first is for the media management for loading images. Then we have the Facebook shimmering dependency along with Fast-Android-Networking and using the recyclerview in the project.

Now we are going to create a new layout called layout_item.xml within the layout folder. Please add the following code:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/item_container">

    <androidx.appcompat.widget.AppCompatImageView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:id="@+id/img_item_avatar"
        android:padding="4dp"
        app:layout_constraintTop_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_item_id"
        style="@style/TextAppearance.AppCompat.Medium"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/img_item_avatar"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Pokemon No" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_item_name"
        style="@style/TextAppearance.AppCompat.Large"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@id/tv_item_id"
        app:layout_constraintTop_toBottomOf="@id/tv_item_id"
        tools:text="Pokemon Name" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_item_email"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@id/tv_item_name"
        app:layout_constraintTop_toBottomOf="@id/tv_item_name"
        tools:text="Pokemon Attribute" />
</androidx.constraintlayout.widget.ConstraintLayout>

Now create another layout within the folder called layout_shimmer and then add the following code:

<?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:id="@+id/shimmer_container"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <androidx.appcompat.widget.AppCompatImageView
        android:layout_width="60dp"
        android:layout_height="0dp"
        android:id="@+id/img_shim_avatar"
        android:background="@color/colorGrey"
        android:padding="4dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_shim_id"
        android:background="@color/colorGrey"
        style="@style/TextAppearance.AppCompat.Medium"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@+id/img_shim_avatar"
        tools:text="#025" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_shim_name"
        android:background="@color/colorGrey"
        style="@style/TextAppearance.AppCompat.Large"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/tv_shim_id"
        app:layout_constraintTop_toBottomOf="@id/tv_shim_id"
        tools:text="Pikachu" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_shim_email"
        android:background="@color/colorGrey"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/tv_shim_name"
        app:layout_constraintTop_toBottomOf="@id/tv_shim_name"
        tools:text="Electric"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Let’s tackle the activity_main.xml in the layout folder and add the below code but before adding let’s provide some context to the XML:

  • We are going to add the ShimmerFrameLayout
    • Within the shimmerframelayout we are going to add some placeholders inside a LinearLayout.
    • Note: that the added placeholder displays multiple times to create the appearance as a list

Then we will add a recyclerview that will display the list of data fetched after executing the network request from the API.

<?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"
    tools:context=".MainActivity">

    <com.facebook.shimmer.ShimmerFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/frame_shimmer"
        android:orientation="vertical"
        android:layout_gravity="center">
        <!-- Add 20 Placeholder -->
        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
        </androidx.appcompat.widget.LinearLayoutCompat>
    </com.facebook.shimmer.ShimmerFrameLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/list_view"
        android:visibility="gone" />

</androidx.constraintlayout.widget.ConstraintLayout>

Create we need to create a data class User: 

import com.google.gson.annotations.SerializedName

data class User (
    @SerializedName("id")
    val id: Int = 0,
    @SerializedName("name")
    val name: String = "",
    @SerializedName("email")
    val email: String = "",
    @SerializedName("avatar")
    val avatar: String = ""
)

Then create an adapater to c

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.programmingninja.crius.R
import kotlinx.android.synthetic.main.layout_item.view.*

class Adapter(private val users: ArrayList<User>) : RecyclerView.Adapter<Adapter.DataViewHolder>() {
    class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(user: User) {
            itemView.tv_item_id.text = "No: ${user.id}"
            itemView.tv_item_name.text = "Hello: ${user.name}"
            itemView.tv_item_email.text = "E: ${user.email}"
            Glide.with(itemView.img_item_avatar.context).load(user.avatar).into(itemView.img_item_avatar)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = DataViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_item, parent, false))

    override fun getItemCount(): Int = users.size

    override fun onBindViewHolder(holder: DataViewHolder, position: Int) {
        holder.bind(users[position])
    }

    fun addData(list: List<User>) {
        users.addAll(list)
    }
}

After completing the adapter now select your MainActivity and now time to complete the following kt file:

To keep in mind to start the shimmering effect as soon as the application opens, we add the startShimmer() within the onResume() activity lifecycle and then we stop it with stopShimmer() within the onPause() activity lifecycle method.

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.androidnetworking.AndroidNetworking
import com.androidnetworking.error.ANError
import com.androidnetworking.interfaces.ParsedRequestListener
import com.programmingninja.crius.helper.Adapter
import com.programmingninja.crius.helper.User
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private lateinit var adapter: Adapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setupUI()
        setAPICall()
    }

    private fun setAPICall() {
        AndroidNetworking.initialize(applicationContext)
        AndroidNetworking.get("https://5e510330f2c0d300147c034c.mockapi.io/users").build()
            .getAsObjectList(User::class.java, object : ParsedRequestListener<List<User>> {
                override fun onResponse(responses: List<User>) {
                    frame_shimmer.stopShimmer()
                    frame_shimmer.visibility = View.GONE
                    list_view.visibility = View.VISIBLE
                    adapter.addData(responses)
                    adapter.notifyDataSetChanged()
                }

                override fun onError(anError: ANError?) {
                    frame_shimmer.visibility = View.GONE
                    Toast.makeText(this@MainActivity, "Something went wrong", Toast.LENGTH_LONG).show()
                }
            })
    }

    private fun setupUI() {
        list_view.layoutManager = LinearLayoutManager(this)
        adapter = Adapter(arrayListOf())
        list_view.addItemDecoration(DividerItemDecoration(list_view.context,(list_view.layoutManager as LinearLayoutManager).orientation))
        list_view.adapter = adapter
    }

    override fun onResume() {
        super.onResume()
        frame_shimmer.startShimmer()
    }

    override fun onPause() {
        frame_shimmer.stopShimmer()
        super.onPause()

    }
}

Take forcus on the following code below to stop the shimmering effect and get the recyclerview to become visible after the network request is executed and data populate in the recyclerview 

override fun onResponse(responses: List<User>) {
    frame_shimmer.stopShimmer()
    frame_shimmer.visibility = View.GONE
    list_view.visibility = View.VISIBLE
    adapter.addData(responses)
    adapter.notifyDataSetChanged()
}

Done

This is all that is needed to fire the application. Hope you enjoyed the read if you need anything else message me for additional assistance.

Happy Learning!!

Tagged under: android, shimmer

What you can read next

allowBackup: Android’s Attributes
Gradient Views w/Swift
When over Switch in Kotlin

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Categories

Recent Posts

  • Gesture Controls for Android w/Kotlin

    Incorporating Gesture controls in your android ...
  • Android Rating: In-App Review API

    An app rating and reviews are crucial if you wa...
  • QR Reader in Android w/ Kotlin

    Turn your phone's camera into a QR scanner...
  • Creating Advance Custom Snackbar w/ Kotlin

    Ask 100 different developers about what they fi...
  • Swift Has Tuple

    Swift provides us with a type called Tuple whic...

© 2017. All rights reserved. Designed by Dauris Little

TOP
This site uses tracking cookies to personalize content and ads. AcceptLearn More