Custom Android Views: Carousel RecyclerView

I would like to start off by saying that this is my first blog post ever, so please feel free to let me know your criticisms and suggestions.

You can view the all of the source code for this here:
https://github.com/SupahSoftware/AndroidExampleCarousel

In this article, we will go through how to create the following recycler view animation

Image for post
Image for post

Here are the libraries you will need in your app level build.gradle file

build.gradle

Next we’re going to start building up our custom RecyclerView code. Let’s create a new class and call it HorizontalCarouselRecyclerView.kt

HorizontalCarouselRecyclerView.kt

This is where almost all of our code will live. Let’s create a function that allows us to initialize our RecyclerView with everything that we need.

A few notes on this piece. We make our LinearLayoutManager horizontal, you’re welcome to make yours vertical if you’d like, but this code will be written to work with horizontal.

We want to register an AdapterDataObserver so that we can update all of our children when new data is set. It’s good to hide stuff like this away in view code rather than in the Activity or Fragment.

As for setting the padding, we want to pad the RecyclerView so that the first and last children in the RecyclerView can make it to the center of the screen. Then we call scrollToPosition(0) to make sure we start at the beginning of the list.

Lastly, we setup an onScrollListener so that every single pixel that the recyclerView is scrolled, all of its children’s size and color will be updated.

Let’s take a deeper look into the onScrollChanged() call now. Let’s add the below code to our custom RecyclerView

The most important parts of this function are that we are iterating through all the RecyclerView’s children and we are going to setup a scale and color for that view.

We are going to use a Gaussian scale factor for the children, which will allow us to scale the view larger in the center of the screen, and smaller towards the edge of the screen. Let’s dive deeper into that getGaussianScale() call now.

Now, this a bit complicated. But if you look up the base function for a Gaussian curve, it will make a bit more sense.

Image for post
Image for post

In the above Gaussian function, alpha (a) is the magnitude of the bell curve (scale that we want the view to be in the center of the screen), x is the child’s horizontal center, b is the RecyclerView’s center, and c is the ‘spread’ of the bell curve. The higher c is, the wider the bell curve and the more the views will be scaled when at the edge of the screen. This should explain everything in the getGaussianScale() method, except for the minScaleOffset. We need that because without it, the method would return us a value from zero to ScaleFactor. If we left it at that, our views would be scaled down to zero at the edge of the screen. We want them at normal size at the edge of the screen, so our offset is 1f.

So far, everything above should cover the scale of the view in relation to the screen position. But we’re missing one thing. Let’s setup our RecyclerView in our activity_main.xml

activity_main.xml

The most important line here is android:clipToPadding=”false”. This allows the custom padding to work properly in our initialize function. Without this line, the children will clipped by the RecyclerView padding.

We now have everything setup properly so that our views are scaled according to their position on screen.

Let’s move onto changing the view colors along with the scale

Moving back to HorizontalCarouselRecyclerView.kt, we need some new member variables

HorizontalCarouselRecyclerView.kt

We will use a value between the activeColor and inactiveColor based on its screen position. We will be passing in a list of views to the RecyclerView that we want to change colors because the RecyclerView shouldn’t directly know about random views in a random view layout. We’ll leave that part up to whoever is implementing this so they can choose what views change color.

We now need a way to pass in the views to our custom RecyclerView. Let’s add a method to HorizontalCarouselRecyclerView.kt

HorizontalCarouselRecyclerView.kt

Lastly, add the method in for changing child view colors

It’s very important to note here that for every view type you intend to change colors for, you will need to add a check in the ‘when’ block for that view type. This is because no Android view’s color is set the same way, so we have to handle each case explicitly. However in our case, we are only changing an ImageView and a TextView, so that is all we need to handle right now.

So we take in the ‘scaleValue’ that we used to scale our view with. It has a range from 1–2. For our ColorMatrix that we will use to set the color on our ImageView, we will need a value from 0–1, so we have to do some math to correct the range. Same thing for the alphaPercent, but we use the 1–2 range to calculate us a value from 122.5–255, because alpha is not set with a 0–1 value.

The ArgbEvaluator allows us to calculate a color value between two colors at a certain point in that scale. This allows us to smoothly transition between our two colors depending on screen position.

The last thing we need to do to make this compile, is setup our adapter and RecyclerView in our Activity/Fragment. Let’s head into MainActivity.kt

MainActivity.kt

The important bit here is that we simply call initialize on our custom RecyclerView and pass in the adapter. The adapter can be created however you would like, it just needs to extend RecyclerView.Adapter and include the proper boilerplate to bind your views.

Also, we pass in the list of views that we want to change color across the screen.

Lastly we set our data/list of items on the adapter and everything else is history.

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store