How to Implement Shimmer Load in Android
Hi, in this post, I will show you how to implement Shimmer Load in Android application. After reading this post hopefully you can implement shimmer load in your Android project. Alright let's get started.
What Will I Learn?
- Logic of how shimmer load works.
- Implement shimmer load in your project.
Requirements
- Android Studio
- Knowledge of Java
Difficulty
- Basic
Tutorial Contents
So maybe you are wondering, what exactly is shimmer load. This is a screenshot of Youtube apps on iOS.
Shimmer load is basically a placeholder that is shown when your apps is loading, for example when fetching data from an API.
There are a lot of shimmer load library which works a bit different, but in this post I will be using a library from Facebook called shimmer-android.
The logic behind facebook shimmer load is basically switching view between two layout. In Android it is basically playing with layout visibility.
In this tutorial, I will make an example of searching movie data from imdb API.
Curriculum
1. Install Dependency
To install this dependency, simply add implementation 'com.facebook.shimmer:shimmer:0.1.0@aar'
in your application build.gradle
file.
This is my entire build.gradle file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "com.steven.example.shimmerloadexample"
minSdkVersion 19
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.0.2'
implementation "com.android.support:recyclerview-v7:27.0.2"
implementation 'com.facebook.shimmer:shimmer:0.1.0@aar'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
2. Create A Placeholder
The next thing is creating a placeholder for the shimmer load. For the movie list item I will have the end result looks like this:
So we need to create the place holder similar to our list item. The place holder I made looks like this:
This is my entire placeholder file with background colorShimmer #DDDDDD:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="160dp">
<View
android:id="@+id/view_image"
android:layout_width="120dp"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:background="@color/colorShimmer" />
<View
android:id="@+id/view_title"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_margin="8dp"
android:layout_toEndOf="@+id/view_image"
android:background="@color/colorShimmer" />
<View
android:layout_width="80dp"
android:layout_height="24dp"
android:layout_above="@id/view_type"
android:layout_alignParentEnd="true"
android:layout_margin="8dp"
android:background="@color/colorShimmer" />
<View
android:id="@+id/view_type"
android:layout_width="160dp"
android:layout_height="24dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_margin="8dp"
android:background="@color/colorShimmer" />
</RelativeLayout>
3. Use Placeholder
Now it's time to use the placeholder that we've created. In your activity/fragment layout add ShimmerFrameLayout with the place holder inside it. In my example I have ShimmerFrameLayout and RecyclerView, when fetching data ShimmerFrameLayout will be shown and starts its animaton, and RecyclerView will be hide. Once all the data has been fetch and added to RecyclerView, RecyclerView will be shown, and ShimmerFrameLayout will be hide and stop its animation.
My activity_main.xml
file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:shimmer="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical"
tools:context="com.steven.example.shimmerloadexample.ui.MainActivity">
<android.support.v7.widget.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:theme="@style/Theme.AppCompat.Light"
app:queryHint="Search here" />
<com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/shimmer_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
shimmer:duration="800">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/shimmer_placeholder" />
<include layout="@layout/shimmer_placeholder" />
<include layout="@layout/shimmer_placeholder" />
<include layout="@layout/shimmer_placeholder" />
<include layout="@layout/shimmer_placeholder" />
<include layout="@layout/shimmer_placeholder" />
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
And my 'MainActivity.java' looks like this:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private SearchView mSearchView;
private ShimmerFrameLayout mShimmerLayout;
private RecyclerView mRecyclerView;
private RecyclerViewAdapter mAdapter;
private List<Movie> mMovieList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSearchView = findViewById(R.id.search_view);
mShimmerLayout = findViewById(R.id.shimmer_layout);
mRecyclerView = findViewById(R.id.recycler_view);
mSearchView.setIconified(false);
mMovieList = new ArrayList<>();
mAdapter = new RecyclerViewAdapter(this);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
mRecyclerView.setAdapter(mAdapter);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
fetchData();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
@Override
protected void onPause() {
super.onPause();
mShimmerLayout.stopShimmerAnimation();
}
private void fetchData() {
mShimmerLayout.setVisibility(View.VISIBLE);
mShimmerLayout.startShimmerAnimation();
String keyword = mSearchView.getQuery().toString();
keyword = keyword.replace(" ", "+");
RetrofitSingleton.getInstance().getRestAPI().searchTitle(keyword, 1, Config.API_KEY).enqueue(new Callback<SearchMovie>() {
@SuppressWarnings("ConstantConditions")
@Override
public void onResponse(@NonNull Call<SearchMovie> call, @NonNull Response<SearchMovie> response) {
if (response.isSuccessful()) {
mMovieList = response.body().Search;
mAdapter.addItems(mMovieList);
mAdapter.notifyDataSetChanged();
mShimmerLayout.stopShimmerAnimation();
mShimmerLayout.setVisibility(View.GONE);
mRecyclerView.smoothScrollToPosition(0);
}
}
@Override
public void onFailure(@NonNull Call<SearchMovie> call, @NonNull Throwable t) {
if (!call.isCanceled()) {
t.printStackTrace();
}
mShimmerLayout.stopShimmerAnimation();
}
});
}
}
4. Final Result
Now let's look at the result.
In my example I have a search view. Let's try and search "black panther", once I press enter on the keyboard it will run fetchData();
and inside it I have set the visibility of ShimmerFrameLayout to visible and start its animation.
Once 'fetchData();` response is successful and data has been added into RecyclerViewAdapter, ShimmerFrameLayout visibility will be set to gone and animation will be stop.
Documentation
- You can check out facebook shimmer load library here: https://github.com/facebook/shimmer-android
- If you want to check out the example I made in this post, you can visit here: https://github.com/steven-tjg/shimmering-load-example
Posted on Utopian.io - Rewarding Open Source Contributors
@steven.tjg, Contribution to open source project, I like you and upvote.
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
Hey @steven.tjg I am @utopian-io. I have just upvoted you!
Achievements
Suggestions
Get Noticed!
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x
Congratulations @steven.tjg! You received a personal award!
Click here to view your Board
Do not miss the last post from @steemitboard:
Congratulations @steven.tjg! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!