Android Skeleton Content Loader šŸ’€

Eudy Contreras
Android Dev Nation
Published in
5 min readApr 5, 2020

--

A guide for easily adding dynamically generated skeletons and shimmer loading effects to you android application āœØ

Skeleton-Bone library Demo screens

You are most likely well aware of what they are. Everyone is using them! But if you havenā€™t seen them before! Skeletons are a way to communicate to the user that the content is loading while at the same time providing a close preview of what the content will more or less look like. It can be arguably said that:

  • Skeletons are clean
  • Skeletons are elegant and appealing
  • Skeletons are easy to implement
  • Skeletons are engaging
  • Skeletons make content loading feel faster.

The primary goal!

The purpose of this article is to show you how to dynamically transform your existing views and layouts into skeletons while their content is loading and even have the content load progressively as it becomes available!

The current problem

If you have already tried to add skeletons to your project, by now you know that you usually have to create the skeleton layout for your content separately. This can be tedious and can easily become unmaintainable. Adding extra views or wrapping your layouts inside Shimmer Effect Wrappers or other skeleton wrappers also leads to an increase in the complexity of your layout hierarchies that can even impact the performance of your app.

Keeping UX in mind āœØ

It is important that the user has the best experience possible, even while they are waiting for content to become available. The loading state of the application must be elegant and visually appealing. When using skeletons it is also important that the skeleton representations of the views or layouts are as close as possible to how the content will actually look.

What Skeletons aim to achieve

  • A seamless transition between loading and content states.
  • A high level of similarity between loading and content screens.
  • Available content should be elegantly revealed to the user.
  • Perceived loading time must be short.
  • A satisfactory user experience when waiting for content

How to achieve this?

There are many ways to solve this problem, but in this article I will show you how to solve it using the Skeleton-Bones library.

Skeleton-Bones can dynamically generate animated skeleton drawables for any View and ViewGroup. In this guide I will show you how to use it in order to create concise skeletons that will fit your appā€™s design seamlessly. This will boost your productivity while allowing you to keep a high level of maintainability for your ever changing views and layouts šŸ˜

Why use Skeleton-Bones?

  • Lightweight and easy to use
  • Non-invasive, No changes to existing code required.
  • No layout nor view wrapping which creates complex hierarchies
  • No mock layouts needed
  • Pixel perfect skeleton bone placing
  • Disposed when no longer needed
  • No boilerplate
  • Progressive content reveal
  • Uses data binding
  • Highly performant
  • Extremely customisable
  • Code-free use

No time Take me to the source code āŒ›. Itā€™s well documented and contains a wiki page. Youā€™ll find everything you need to get started.

Getting started

The recommended way of using bones is to apply it and modify it using the power of data-binding. Binding a skeleton attribute creates and applies Skeleton or Bone drawables under the hood. It is also possible to customise Bones by directly accessing its properties through an instance of it. Instances of a SkeletonDrawable or BoneDrawable can be modified using both builder and property accessors patterns.

Adding it to your project

Please keep in mind that the latest version might have changed since the time this article was written.

dependencies {  
implementation 'com.github.EudyContreras.Skeleton-Bones:v1.3'
}

Once Bones is added to your project. You can now enable skeleton loading on any View or ViewGroup. In order to make a layout ā€œSkeleton loading enabledā€ simply add skeleton attributes to it. In the example below youā€™ll see how this is done. For a complete list of attributes check out the repository docs.

Example Layout

The above layout will result in the skeleton below. As you can see, the two images are independent state owners so they are loaded independently within the same skeleton. Any element can be an independent state owner by simply letting it listen to state changes. For a better understanding of how this works I recommend you install and inspect the demo app, also check out the demo branches for more live demos. šŸ™Œ

ā€œA skeleton allows you to gradually load content as it becomes available. This can create the feeling that the content is loading fastā€

Demo-1 screen

The skeleton you see above is a single Foreground Drawable which is rendered on top of the Parent layout. Each bone is drawn directly on top of its respective view. Even the optional fake shadows.

But wait!! What if we donā€™t know the size of the view prior to creating the layout? What if I donā€™t want to show the view and just show a shimmer effect?, etcšŸ¤”. Skeleton-Bones solves all of that! Check out the repository docs

If you rather not use data-binding. You can use the extension function available for your view or view group.

val viewGroup: ViewGroup = getSomeContainer()

viewGroup.applySkeletonDrawable().apply { }

Or you can use the builder pattern by calling build on the instance of the drawable

val viewGroup: ViewGroup = getSomeContainer()

SkeletonDrawable.create(viewGroup)
.build()
.setEnabled(true)
.setAllowSavedState(true)
.withShimmerBuilder {
setThickness(10.dp)
setTilt(0.3f)
}
.setCornerRadius(10f)

You can also of course use accessor patterns and set the values directly.

val viewGroup: ViewGroup = getSomeContainer()SkeletonDrawable.create(viewGroup).apply { 
this.getProps().apply {
this.enabled = true
this.allowSavedState = true
this.shimmerRayProperties.apply {
this.shimmerRayThickness = 10.dp
this.shimmerRayTilt = 0.3f
}
}
}

I hope you found my first post on Medium useful šŸ˜ƒ. You can find the source code and some detailed documentation in my Github repository if interested!

Feel free to leave a comment! Ohh! And one more thing, If you liked this article or found it useful make sure to šŸ‘

--

--

Eudy Contreras
Android Dev Nation

Programming enthusiast with an interest for Android Application Development.