4th Street Bar Hive-Bar

Hive-Bar Powered by Hive beta-fdb5b5b

Community post

How to Implement Shimmer Load in Android

cover.png


Facebook Shimmer

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.
youtube-ios-shimmer.jpeg
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:


item_movie.png


So we need to create the place holder similar to our list item. The place holder I made looks like this:


placeholder.png


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.


app.png


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.


load.png



Once 'fetchData();` response is successful and data has been added into RecyclerViewAdapter, ShimmerFrameLayout visibility will be set to gone and animation will be stop.


final.png

Documentation



Posted on Utopian.io - Rewarding Open Source Contributors

7 upvotes $4.89

Replies (5)

Review before signing

Posting as . Signing with . Keychain permission: Posting. Hive Keychain will ask you to approve this action next.


  
Technical details

Operation fingerprint: