Menu Animation Android

Hi everyone, this is Sujith. Today I am going to talk about a different kind of animation in RecyclerView.

This video shows the animation I have made in the RecyclerView. For this, I have written my own code to load and cache images. You can use Picasso or Glide to do the same. I will tell you how it works. Then you will have a better understanding of how to write custom components and draw bitmaps and to manipulate views according to your requirements.

The first part is to create a view which allows you to scroll image inside horizontally inside the view.

SliderImageView

For this, you need to know how to draw a bitmap in views. It’s pretty simple than you think. Create a new class and extend it to view.

You need to override the onDraw() and onMeasure() methods for this example.

OnDraw() To draw something on the view, you have to override this method to get the canvas of this view.
onMeasure() To get whenever the view size is measured, you will know that my this method.

Now lets see how to draw a bitmap. The bitmap is nothing but the collection of raw pixels.

In this code snippet, we tried to draw a bitmap, but lets see what all it requires.

To draw a bitmap, you need a bitmap, source bounds(Rect), draw bounds(Rect) and a paint object.

  1. Bitmap is whatever image file you loaded into memory.
  2. SourceBounds is just a Rect object which contains the bounds details of the image portion we are going to draw on the canvas.
  3. DrawBounds is also a Rect object which defines where you want to draw the image (In our case, it is the bounds of the entire view itself).
  4. Paint holds the style and color information about how to draw geometries, text, and bitmaps.
Rect object will have the boundary variables which are left, right, top and bottom

The drawBounds object should have left = 0, top = 0, right = viewWidth and bottom = view height. We have to keep the view square, in this case, the right and bottom will be equal.

The sourceBounds will have the bounds of the portion of the image. left = x, top = 0, bottom = view height, right = x + view height. Since the view is square, the bounds width should always have to be equal to bounds height. To do the sliding, all you have to do is change the value of x according to the fraction. But x cannot be greater that the bitmapWidth — viewWidth. If it exceeds, then the rect will go out of bounds and only rect part of the image will be drawn on screen.

In this video, the first image is the fully loaded image. The blue dashed rectangle represents the source bounds. The second image shows the drawn part of the image. If I change the position of the rectangle, whatever is inside the rectangle will be drawn in the second image.

Not lets apply the idea in our custom view, the class will look like this

Here we are going to use mAnimationFactor(float) variable to position the source bounds of the bitmap. All you need to find is the range of the bitmap rect sliding area to slide the rect over the bitmap. The range is the distance between 0 to (bitmap width — view width). Now multiply mAnimationFactor to the range and you will get the left of the source bounds rect. Add the source bounds left to the view width will give you the value of the source bound’s right(mAnimationFactor must be between 0–1). That’s it, sliderImageView.setAnimationFactor() will show the portion of the image according to the float value you pass.

RecyclerView

Lets create an XML for the items of RecyclerView.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coloFillLayout"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginBottom="40dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="40dp">

<android.support.v7.widget.CardView
android:id="@+id/contentView"
android:layout_width="150dp"
android:layout_height="120dp"
android:layout_centerInParent="true"
app:cardElevation="15dp"
app:cardMaxElevation="15dp">

<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center"
android:padding="20dp"
android:textColor="#232323"
android:textSize="14sp" />

</android.support.v7.widget.CardView>

<com.hsalf.menuanim.widgets.SliderImageView
android:id="@+id/sliderImageView"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerInParent="true"
app:cardElevation="15dp"
app:cardMaxElevation="15dp" />

</RelativeLayout>

The above XML will form the layout item like this. The green color layout is just an empty view with color. Just not included in this XML to avoid confusions in the code, we are not gonna refer that view anywhere.

I am not going to go deep into the creation of RecyclerView or its adapter. Lets just keep on learning about the animations and necessary snippets for it. I have created a viewHolder for the adapter of the recyclerView.

content is a textView which shows the details of the item, contentView is a cardView which holds the content(TextView) and imageCard is the view we created to show and slide our images.

Now lets add a method in adapter to animate views, in our case, slide views.

All the code lines have been explained in the code comments. Now, all we have to do is to pass the viewHolder object of the RecyclerView to slide the views inside the item according to the position on scrolling the RecyclerView.

Create a scroll listener and override onScrolled() method. From there you can get items visible on RecyclerView and their viewHolder objects. Take them all and pass it to the method we created above in the adapter.

That’s it!, The method will calculate the item position on the screen, calculates the sliding distance and slides the view inside the listItem on scrolling the list.

This blog is not about creating this animation. This is about how you can think differently and create something new. Check SmileyRating for my another creation.

You can download the source for this project from the repository below,