What is a Shimmer Effect?
Its an effect to show a loading status. Instead of using a progress, Shimmer effect creates a better design for ux. It mimics the page’s layout by showing its elements in a shape similar to the actual content as it is loading and becoming available (i.e. when network latency allows).
How to implement this on Android?
There is is an Android library, Shimmer, that provides an easy way to add a shimmer effect to any view in your Android app.
So lets start!
First include the library dependency:
dependencies {
// Shimmer
implementation 'com.facebook.shimmer:shimmer:0.5.0'
}
Now create a layout list_placeholder_layout.xml
that will act as a placeholder while content is loading.
In my example I have an imageView to display the image of the animal and two textViews for the name and the type. So the layout is something like this:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="10dp">
<androidx.cardview.widget.CardView
android:id="@+id/animal_image"
android:layout_width="120dp"
android:layout_height="150dp"
android:backgroundTint="@color/gray"
app:cardCornerRadius="20dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/animal_name"
android:layout_width="120dp"
android:layout_height="30dp"
android:layout_marginStart="20dp"
android:layout_marginTop="30dp"
android:backgroundTint="@color/gray"
app:cardCornerRadius="10dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_constraintStart_toEndOf="@id/animal_image"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/animal_type"
android:layout_width="120dp"
android:layout_height="30dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:backgroundTint="@color/gray"
app:cardCornerRadius="10dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_constraintStart_toEndOf="@id/animal_image"
app:layout_constraintTop_toBottomOf="@id/animal_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
Once the layout is created we need to include it in the main layout activity_main
, where the recyclerView is situated.
To do that, we include <com.facebook.shimmer.ShimmerFrameLayout>
<?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=".ui.main.MainActivity">
<com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/shimmer_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:duration="800">
<!-- Adding 8 rows of placeholders -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="5dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
In the next step, we just need to tell Shimmer when to start and stop the animation.
- We should start the Shimmer when we fetch the list of items.
binding.shimmerView.startShimmer()
- We should stop the Shimmer when we get the list of items.
binding.shimmerView.stopShimmer()
Also, we should hide the visibility of the Shimmer Frame Layout, when we have the list of items.
binding.shimmerView.isVisible = false
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//Start Shimmer
binding.shimmerView.startShimmer()
viewModel.getAnimals(10)
viewModel.animalList.observe(this) {
initRecyclerView(it)
}
}
private fun initRecyclerView(animalList: List<Animal>) {
binding.recyclerView.layoutManager = LinearLayoutManager(this)
val adapter = AnimalAdapter(animalList)
binding.recyclerView.adapter = adapter
//Stop Shimmer
binding.shimmerView.stopShimmer()
//Hide Shimmer view
binding.shimmerView.isVisible = false
}
}
And that's all!!
If you want to check the whole project here you have the link: ShimmerEffectAndroid
Don't forget to like and share! Thank you! :)
Useful links:
Top comments (0)