Introduction
Layout
Touch
Animation

Touch Gesture-Activated Animations on Android Mobile


Introduction: Creating Your Project

Hello! Welcome to my How-To Guide on how to implement animations that are triggered by touch gestures on the Android mobile platform. Below, you can see an image of what the finished product will look like after following this guide. This guide will focus on using touch gestures to recognize a swipe and make a panel fly out from off the screen. After getting through the guide, you should be able to take what you have learned and apply it to any future Android mobile applications that you develop, to make your user interface seem lively and responsive!



In order to get this project started, we are going to have to set up a few initial files, that way we can get to the fun part and actually see our work come to life! So first, open up Android Studio, and create a new project, by going to File -> New -> New Project... in the top menu.


You should now be on the new project screen. The dialogue box will ask you to name your application and company domain, as well as where you want to save the project. Feel free to name your application whatever you wish, and the company domain doesn't really matter. Don't worry if you don't own a website, you can put whatever you want in that field. After that, hit the Next button.


Afterwards, a new dialogue will pop up, asking you what platforms you want your application to target, or run on. The settings I have selected will work perfectly fine for our purposes. You only need to worry about developing for phone and tablet at the moment. Once you are happy with your settings on this page, click the Next button again.


Now, you will be on a screen asking what type of activity to create to start your project off. Activities are the building blocks of a mobile Android application. Think of an Activity as a scene that carries out certain functions within your application. We are going to be building our animated menu from scratch, so go ahead and select Empty Activity. Don't worry, the boring part is almost over!


Finally, for the last step, you just have to name your activity and activity layout. The Layout of an activity defines the appearance of the scene, and the interface components present within the screen, but we will get to that soon enough. For now, just label your Activity and Layout whatever you like. The default of "MainActivity" will work fine, and it even populates the Layout field accordingly. Now click Finish so that we can start coding!


Defining the Layout and Familiarizing Yourself with the File Structure

After you have created your project, you will be brought to the main editor screen, with 2 files open: "MainActivity.java," and "activity_main.xml." (These are just what mine are called, if you named your activity something different then they will be the same, but with the name you specified. When creating a mobile Android application, your project will consist of both Java and XML files. The XML files will define the Layout of your application's Activities, as well as Resource files that store things such as pre-defined styles, strings, colors, and other things. The Java files are where you will be writing code that will make your application work. Through the Java files, you will also be able to manipulate XML elements in your Layout, which is what we will be doing in order to animate the menu (which is a Layout XML element!). Right now, the code in the MainActivity.java file is pretty bare, all it does currently is set the view of the application to the layout defined in the corresponding XML file, "activity_main.xml."


Before we jump into the XML file and start designing the menu for our activity to display, let's take a look at the file structure via the left column of your screen. Navigate to where it shows a directory titled "res," and click the little arrow so that it expands. Then do the same for the directory titled "values." Now you should see 3 XML files: "colors.xml," "strings.xml," and "styles.xml." Double click each of these so that they are open in your main screen.


First, let's look at the strings file. In this file, all you should see is only a single XML string element, with the name "app-name" and whatever you defined your application's name to be. All of these files belong to a section that is known as the "Resources" of your application. The files in your resources directory contain different types of information that can be used throughout your project, in both the XML and Java files. The strings file, basically just lets you define strings that can be used throughout your project, in a way that most programming languages let you define variables. Each string entry in the string file has a name, in our case "app-name," that can be used to reference the value within the <string> tag. The colors file stores information similarly, however, instead of storing strings, it stores color values in the form of hexadecimal numbers (#000000 for black, #FFFFFF for red, etc.). The styles file is a little bit more complicated, but think of it as a place to store templates for the layouts you create (akin to CSS classes). For example, if you have several text items that you want to display in a menu, and you want them to all look the same way, but don't want to type the same properties out for each text item, then you would create a style that contains all the properties that you desire. Then you could just apply that style to all your text items with one line, and it would have the same effect as if you typed the properties out for each one. We are going to go ahead and fill out a few lines for each of these 3 XML files, so that we can use the references later throughout our project. The elements are pretty self-explanatory, and they will all make sense once we actually use them in the layout and Java code. After you are done and your files look like the screenshots below, continue reading and we can start constructing the layout.






Now it is time for designing our Layout! Basically, after we are done with this step, we will have all the elements that we need to start animating our scene! To get started, navigate to the "activity_main.xml" file, or whatever it is called in your project. What's really cool about the Android Studio SDK is that it shows you a live preview of what the Layout would look like on an Android device running your application. You should be able to see a Preview on the right of your screen. If not, look for the button labeled "Preview", right under the button labeled "Gradle." All your XML file should have in it is a Relative Layout element and a Text View.


So basically, Android Layouts are made up of two types of components: Views and View Groups. A view is any type of element that can be placed on the screen, such as text, images, buttons, etc. A view group is a special type of container, that groups views together. An example of a view group would be a list or grid, that arranges views in a certain pattern. The Relative Layout element that we have right now is a View Group, and that is what we will be using as the outer-most parent element of our layout. Relative just means that we can position children within the object (other views) in relation to one another. So we can place elements above, below, and on the sides of other elements. The Text View in the file just displays the little "Hello World!" message that you see at the top of the Preview screen. For our application, all we are going to need to add to this file is a Linear Layout, which will enable us to group Text Views vertically to create our menu, and some Text Views to represent text on the screen. Below, I have included the code that you should place in the XML Layout file. Don't worry, I will explain it all after you finish copying it.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.tonyanziano.how_to_application.MainActivity">

    <LinearLayout
        android:layout_width="250dp"
        android:layout_height="500dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="-200dp"
        android:orientation="vertical"
        android:id="@+id/options_menu"
        android:background="@color/android_green">

        <TextView
            android:id="@+id/menu_header"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:text="@string/menu_header"
            android:textAppearance="@style/menu_header"
            android:layout_gravity="center_horizontal"
            android:gravity="center_vertical"/>
        <TextView
            android:id="@+id/menu_item1"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="@string/menu_item1"
            android:textAppearance="@style/menu_item"
            android:layout_gravity="center_horizontal"/>
        <TextView
            android:id="@+id/menu_item2"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="@string/menu_item2"
            android:textAppearance="@style/menu_item"
            android:layout_gravity="center_horizontal"/>
        <TextView
            android:id="@+id/menu_item3"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="@string/menu_item3"
            android:textAppearance="@style/menu_item"
            android:layout_gravity="center_horizontal"/>
    </LinearLayout>

    <TextView
        android:id="@+id/sideways_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/sideways_text"
        android:textAppearance="@style/sideways_text"
        android:layout_toRightOf="@id/options_menu"
        android:layout_centerVertical="true"
        android:rotation="-90"
        android:layout_marginLeft="-160dp"/>


</RelativeLayout>

So now you should have a little green rectangle on your Preview screen that is only slightly visible. This is good, because we are going to have the user swipe from left to right, starting on the visible part of the green rectangle, to get the menu to fly onto the screen. The Linear Layout in your XML file is a View Group that will represent our Menu. In the Layout file, we give every element a width and height, through the properties: "android:layout_width" and "android:layout_height. Everything you see under an XML element that starts with "android:" is a property. These properties allow us to style elements and position them. Most of the properties are self-explanatory, however there are some that we should go over. In the Linear Layout element, we have a property called "orientation." This is specific to Linear Layouts. Since they are like lists, they can have a horizontal orientation, or a vertical orientation. Vertical, means the Views within the Linear Layout are stacked on top of each other, vertically, like a menu, Horizontal orientation means that the Views are in line with eachother, much like when you have an input field with a button next to it.

The next property, "id," is one of the most useful properties in the Layout XML files. It allows us to specify a name by which we can refer to that specific Layout View or View Group in the future, both in the Java and XML code. The id is defined by putting "@+id/[ID HERE]" if you are creating a new id. If you just want to reference an already created id later on in the XML, you omit the "+" and just use "@id/[ID HERE]." Now we have our menu container defined as "options_menu." On the next line, we simply give it a background color by using the "background" property. Remember filling out that "colors.xml" file? Now we get to use it. By putting "@color/android_green" as the "background" property's value, we are telling the XML file to go to the colors file, and look up the color we entered as "android_green." We defined it as: <color name="android_green">#A4C639</color> So the property fetches the hexadecimal value under that entry and uses it for the background, which is why our box is a delightful light green.

Now, the next few lines just define Text Views that represent visible text on our Menu. Since these are inside a Linear Layout with a vertical orientation, they will be stacked on top of each other. Again, we define id's for each of these, as it will be important to refer to these in our Java code later. We also give the Text Views text by again, using the "strings.xml" file in our resources directory via the "@string/[STRING HERE]" value. It is the same convention as how we defined the menu's color. Recall how I talked about styles earlier, here we use them to style all the menu items without having to type out about 3 lines of code for each Text View. Pretty nifty, huh?

Here, you might be wondering why the Text Views have a height of 0dp (density-indepent pixel). This is because we are using something called "android:layout_weight." When using certain types of layouts, like Linear Layouts, you can define what are called layout weights for each element in the View Group. The higher the number, the more weight the View has in the View Group, meaning it takes up more space. So for our Menu, the menu header has a weight of 2, while all the sub items of the menu have a weight of 1, so that the header stands out.

Last but not least, we have our Text View that is outside of the Linear Layout. This guy will be the text that appears on the unexpanded menu tab. This text is rotated sideways by 90 degrees, hence the name "sideways_text," and the property "android:rotation="-90."





Now, we are ready to start coding in Java!

Recognizing Touch Gestures

Now that we have our Layout set up the way we want it, we can start writing Java code to recognize touch gestures! The first thing that we are going to need is create what is called a GestureDetector class. The way Touch Gesture Detection works in Android is that you first declare a Gesture Detector. This detector will be passed all touch motion events that are picked up by the device's screen. We then need to create something that will process all these touch events. This is where the Gesture Listener class comes in. In most cases, you need to implement functionality for every single type of gesture recognized by Android (swipe, long press, pinch, etc.), however, for our application we only need to recognize a down press on the screen, and a motion that is called a fling (basically a fast swipe). Knowing this, we can just use the convenient SimpleOnGestureListener class. The detector will pass all of the motion events that it detects to the Gesture Listener. The Listener will then determine what type of event it is, and perform an action based on that event! Below is the code for declaring both these classes. Place this code ABOVE the onCreate() function.

//create gesture detector that we will bind listener to
GestureDetector detector;
GestureDetector.SimpleOnGestureListener listener =
            new MyGestureListener();
							 

Now that we have our detector and listeners declared, we need to bind the listener to the detector, so that the detector is aware of its existence. This basically partners the two up, like a touch-event-based super hero duo! Inside the onCreate() function, under where the setContentView() function is called, paste this code:

/bind the detector to the listener
detector = new GestureDetector(this, listener);
						

So our Detector is defined, and is partnered up with the Listener now. However, we still need to define what our Listener does in response to certain gestures. So let's create a new class called MyGestureListener that extends the SimpleOnGestureListener class.

//make a class that extends the simple gesture listener
public class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
	//override the gesture(s) we want to use
	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
		return true;
	}
	//we need onDown
	@Override
	public boolean onDown(MotionEvent event){
		return true;
	}
}
						

With this class, we are going to need to override the functions of the gestures that we are interested in, and make them work for our purposes. The two touch events that we need for our animated menu are the onFling() and onDown() functions. The onFling() function will recognize a swipe from one point to the other, and measure the velocity (direction and speed) of the swipe. This will be useful to us because we don't want the menu to fly out when the user accidentally touches the portion of the menu that's sticking out while hidden. The onDown() function is absolutely necessary as it is called at the start of every touch event, when a finger touches the screen. All we need to do is get the function to return true, so that all touch events are recognized. However, we will need to fill out onFling() as that is where most of our application's functionality will come from.

So, whenever a fling event is detected, on a finger swipe or some similar gesture, the code inside our onFling() function will fire. You can test it if you want by using Android's Log.d() function to output the touch event data to the console, such as velocity and event position. By testing this, we can see that any swipe towards the right of the device will have a positive x velocity. This is important to know, as the sign of the x velocity will tell us which way the user is swiping, and so we can show or hide our menu using this information. Before we fill out the onFling() function, lets add a couple of global variables to the top of our program. Right under where we declared our Gesture Detector and Listener, let's add this to our code:

//speed of swipe at which the menu animation will trigger
final static float MIN_FLING_SPEED = 500f;
//boolean that represents menu state
public boolean menuHidden = true;
						

The first global variable will represent the minimum velocity that a user will have to achieve on a swipe in order to get our menu to fly out from off of the screen. You can play around with the value if you want, but this seemed like a good value for me. The second will represent the state of our menu View, and whether it is on or off the screen. You will see why soon. Now, using these variables, we can finish out filling our onFling() function.

//override the gesture(s) we want to use
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
	//if x-velocity is to the right (positive)
	//and is more than our desired threshold'
	//slide the menu onto the screen
	if((velocityX > 0) && (velocityX > MIN_FLING_SPEED) && menuHidden){
		//animate menu onto screen (IN)
	}
	//if x-velocity is to the left (negative)
	//and is more than our desired threshold
	//slide that menu off of the screen
	if((velocityX > 0) && !menuHidden){
		//animate menu off of screen (OUT)
	}
	return true;
}
						

All we really need for the Touch Recognition portion of our project lies within these two if statements. The first statement checks if the x velocity of a finger swipe is greater than 0 (positive), which means that the swipe is towards the right side of the device. This will indicate the user is trying to show the menu. Before we do anything, we first want to make sure that the velocity of the swipe was above the treshold we just defined, so we don't show the menu on accident. We also want to make sure that the menu is currently off the screen, so that we don't replay the animation when the menu is already shown. Inside this if statement, we will perform our animations that move the menu onto the screen.

The second if statement does exactly the opposite of the first. It checks to see if the velocty of the swipe gesture is negative, indicating that the swipe was towards the left of the device. It also checks that the menu is currently on the screen. Notice that this statement does not check for the velocity threshold, this is because when I was testing left swipes, the max negative x velocity I could get was only about -1 or so. I don't know if this was a bug or what, so I just omitted the threshold requirement. It still works fine in the end. Inside this statement, we will perform our animations that move the menu off of the screen.

We are really getting somewhere now! Just one more thing to do before we can move on to animating the menu. We need to get a reference to our menu, and add a touch listener to the menu that sends all events to our Gesture Detector. So, once again, at the top of our program where we declared the global variables, paste this code:

//reference to menu view
public View menu;
						

Now, find our onCreate() function, and let's programatically grab a reference to our menu's XML representation that we defined in the Layout file!

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	//bind the detector to the listener
	detector = new GestureDetector(this, listener);
   
	//grab a reference of the view we want to detect on
	menu = (View) findViewById(R.id.options_menu);
	menu.setOnTouchListener(new View.OnTouchListener() {
		@Override
		public boolean onTouch(View v, MotionEvent event) {
			//send the touch event to our detector to dispatch to be dispatched to the listener
			detector.onTouchEvent(event);
			return true;
		}
	});
}						
						

The onCreate() function should now look like the above code. What we did is used an incredibly handy function findViewById(R.id.options_menu) to grab a reference to our Menu's XML Layout element that we defined much earlier in the Layout XML file. The function looks in the "id" directory of our project's "resources" directory for the id that we defined in our XML that corresponds to the Linear Layout we made as our menu. Hence the argument, R.id.options_menu. If you recall, we defined our menu's id with the line android:id="@+id/options_menu". The function returns an object to us that we then cast to the type View which matches the global declaration we might a little earlier. Now, we can use this variable to reference the menu object in the Layout.

The second part of this code might look confusing, but it's really quite simple. We take our new menu object reference, and add a touch listener to the view. This listener will only listen for touch events that occur WITHIN the bounds of the View, our menu in this case. So only touch events that come in contact with our menu View will trigger the listener. We then tell the listener to use our Detector from earlier to process the touch event so that the custom listener we wrote catches the gesture. Then we return true to confirm the event.

Finally, let's start animating!

Animating Views on the Screen

In order to animate our menu, we are going to need to add some more variables and references to our code. So let's start at the top of our Java file! You are going to want to add a function called dpToPx() that will convert density-indepent pixels (dp) to regular pixels. We use dp units when we design our layout so that our layout looks uniform across devices with different screen pixel densities. However, there is no way to get the dp value of a View programatically, so we use this function to do the conversion for us with the values that we supplied in the XML. We also need to add some references to the Text Views that we created in our menu View Group. We will also need to create a reference to our RelativeLayout.LayoutParams which will allow us to acces the margin values in our Layout. Changing the left margin value of our menu View is what allows us to move it partially off of the screen and out of the content view. In addition to this, we will declare a few ValueAnimators, which basically control separate animations. Also, a global variable called SCREEN_WIDTH is added to represent the pixel value of the device's total screen width, which we will use later to position the menu. Paste the following code above your onCreate() function:

//screen width (we will need later)
public int SCREEN_WIDTH;
//reference to layout parameters
public RelativeLayout.LayoutParams params;
//reference to menu view
public View menu;
//references to text views
public TextView menuHeader, item1, item2, item3, sidewaysText;
//reference to animations
public ValueAnimator animationIn, animationOut, animationFadeOut, animationFadeIn, animationPromptFadeOut, animationPromptFadeIn;
						

Now, we have to add quite a bit to our onCreate() function. We will use a class called DisplayMetrics to grab the width in pixels of our devices screen, and store it in the variable mentioned above. We will also use the same method we used earlier to grab the XML reference of our menu, but with each of our Text View items, by looking up their ID's in the resources directory. Next, we will use our pixel conversion function, and the dp values we defined in our XML layout to get some pixel values that are important for our animation. initialOffset represents where the menu View Group starts out, -200 dp left of the screen edge. menuWidth is just the width of the menu View Group android:layout_width="250dp". The finalOffset is where we want the left edge of the menu to end up once it is done being animated, this is half of the screen, minus half of the menu's width. So the menu ends up in the middle of the screen.

It's time to create our animations. Animations are very straight forward. First, we instantiate each animation as a separate ValueAnimator class with either .ofFloat or .ofInt following it depending on the type of the value we are modifying over the animation. For our animations that modify the transparency of Text Views, we modify the alpha value, which is an integer, so we use the .ofInt suffix. For moving the menu View Group, we are modifying the x position of the View Group, which is a float value, so we use .ofFloat. The first value passed to this instantiation is the starting value, and the second is the ending value. Once the animation is started, it will interpolate the value from the start value to the end value over a period of time that we define by using the [animation].setDuration() function. The value passed to this function is in milliseconds, so 300 milliseconds is .3 seconds. I found that a full second felt far too slow. So, we are going to set our animations up, to interpolate the position of the menu View Group, and also the alpha value of the Text Views. The animationOut and animationIn animations will control the menu position. While the others will control the alpha values.

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	//get width of device screen because we will need that later
	DisplayMetrics metrics = new DisplayMetrics();
	getWindowManager().getDefaultDisplay().getMetrics(metrics);
	SCREEN_WIDTH = metrics.widthPixels;
	//bind the detector to the listener
	detector = new GestureDetector(this, listener);
	//grab references for all text views
	menuHeader = (TextView) findViewById(R.id.menu_header);
	sidewaysText = (TextView) findViewById(R.id.sideways_text);
	item1 = (TextView) findViewById(R.id.menu_item1);
	item2 = (TextView) findViewById(R.id.menu_item2);
	item3 = (TextView) findViewById(R.id.menu_item3);
	//grab a reference of the view we want to detect on
	menu = (View) findViewById(R.id.options_menu);
	menu.setOnTouchListener(new View.OnTouchListener() {
		@Override
		public boolean onTouch(View v, MotionEvent event) {
			//send the touch event to our detector to dispatch to be dispatched to the listener
			detector.onTouchEvent(event);
			return true;
		}
	});
	//first we have to convert "dp" into pixels
	float initialOffset = (float) dpToPx(-200);
	float menuWidth = (float) dpToPx(250);
	//now to center the menu
	float finalOffset = (((float) SCREEN_WIDTH) / 2) - (menuWidth / 2);
	//create animations
	//we want to translate the menu from the initial offset to
	//the middle of the screen
	animationOut = ValueAnimator.ofFloat(initialOffset, finalOffset);
	animationOut.setDuration(300);
	animationIn = ValueAnimator.ofFloat(finalOffset, initialOffset);
	animationIn.setDuration(300);
	//grab a reference to layout parameters so we can fiddle with margins
	params = (RelativeLayout.LayoutParams) menu.getLayoutParams();
	//animations to alter text opacity
	animationFadeIn = ValueAnimator.ofInt(0, 255);
	animationFadeIn.setDuration(300);
	animationFadeOut = ValueAnimator.ofInt(255, 0);
	animationFadeOut.setDuration(300);
	animationPromptFadeOut = ValueAnimator.ofInt(255, 0);
	animationPromptFadeOut.setDuration(50);
	animationPromptFadeIn = ValueAnimator.ofInt(0, 255);
	animationPromptFadeIn.setDuration(50);
}
						

The behavior that we are trying to achieve with this animation is as follows. We have a sideways Text View on the exposed part of the menu when it is hidden. This text prompts the user to swipe the menu out onto the screen. However, when the menu flies out onto the screen, we don't want this text interfering with the rest of the text on the menu, so we want to make it fade away by altering it's alpha value. We then want to fade in the text that is actually on the menu, because we hide it while the menu is off screen. We will also do this by altering the alpha value of each of the menu item Text Views. When the menu is out and the user wants to hide it, we will perform the reverse, and fade out the menu text, while fading in the sideways text upon completion.

Let's go back to our custom Gesture Listener, where we are able to recognize finger swipes, this is where we will perform our animations. Now that we have the animations set up, all we need to do is figure out when to call them. We decided that inside the first if statement is where we would slide the menu onto the scren. So this is where we need to fade out the sideways text, fade in all the menu text, and move the menu onto the screen so that it is visible. In order to do this, we take each animation object that we have for each of those functions, and we add an Update Listener. Update Listeners are called whenever a frame of an animation is processed, so inside the listener is where we will get each iteration of our updated value as it is being interpolated. For the text-altering functions, this will be the alpha value, and for the menu, this will be the margin position! To do this we merely call [animator].addUpdateListener(), and within the listener's onAnimationUpdate(), we grab the value being updated by casting it to our desired type, then use it to modify whatever value we want. For text, we grab the updated alpha value and use it with the [TextView].setTextColor() function to change the alpha of the text over time.

For the menu's position, we perform the same process. However, instead of the alpha value, we grab the margin value that is being modified. We then take the RelativeLayout.LayoutParams reference we grabbed earlier, and insert the new margin value into it. We then take our menu View Group reference and set its layout parameters to the new updated parameters. Then we call invalidate() so that the updated view is redrawn by the Android graphics engine. If we didn't call the invalidate() function then the menu would not appear to be moving at all. Finally, we add just a regular animation listener to the animation that fades the sideways text out. Regular listeners, in contrast to update listeners, allow us to perform actions at key parts in the animation, such as at the start or end of the animation. This way, we can fade the sideways text out as soon as the menu starts to slide onto the sreen. This is done in the onAnimationStart() function. Finally, we call [animator].start() on the animations that we want to fire in order to bring our project to life. This will cause the menu to move and the Text Views to fade in and out. We need to make sure to update the boolean flag menuHidden that represents the state of the menu's animation.

//make a class that extends the simple gesture listener
public class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
	//override the gesture(s) we want to use
	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
		//if x-velocity is to the right (positive)
		//and is more than our desired threshold'
		//slide the menu onto the screen
		if((velocityX > 0) && (velocityX > MIN_FLING_SPEED) && menuHidden){
			//add an update listener to the animator
			//so we can access the changing value
			animationPromptFadeOut.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
				@Override
				public void onAnimationUpdate(ValueAnimator animation) {
					//grab the updated value
					int value = (int) animation.getAnimatedValue();
					//change text's opacity
					sidewaysText.setTextColor(Color.argb(value, 0, 0, 0));
					Log.d("How-to", " FADE OUT alpha: " + value);
				}
			});
			animationOut.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
				@Override
				public void onAnimationUpdate(ValueAnimator animation) {
					//grab the updated value
					float value = (float) animation.getAnimatedValue();
					//put value into margin parameters object
					params.setMargins((int) value, 0, 0, 0);
					//set the new parameters object to the view's layout
					menu.setLayoutParams(params);
					//invalidate the view so that it is redrawn
					menu.invalidate();
				}
			});
			//we need to add a listener that triggers on the animation end
			animationOut.addListener(new Animator.AnimatorListener() {
				@Override
				public void onAnimationStart(Animator animation) {

				}

				@Override
				public void onAnimationEnd(Animator animation) {
					//set the menu state flag
					menuHidden = false;
				}

				@Override
				public void onAnimationCancel(Animator animation) {

				}

				@Override
				public void onAnimationRepeat(Animator animation) {

				}
			});
			//add an update listener to the animations that fade text
			animationFadeIn.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
				@Override
				public void onAnimationUpdate(ValueAnimator animation) {
					//grab the updated value
					int value = (int) animation.getAnimatedValue();
					//use this value to change the alpha of the text
					menuHeader.setTextColor(Color.argb(value, 0, 0, 0));
					item1.setTextColor(Color.argb(value, 0, 0, 0));
					item2.setTextColor(Color.argb(value, 0, 0, 0));
					item3.setTextColor(Color.argb(value, 0, 0, 0));
				}
			});
			animationFadeIn.addListener(new Animator.AnimatorListener() {
				@Override
				public void onAnimationStart(Animator animation) {
					//start fading out sideways text
					animationPromptFadeOut.start();
				}

				@Override
				public void onAnimationEnd(Animator animation) {

				}

				@Override
				public void onAnimationCancel(Animator animation) {

				}

				@Override
				public void onAnimationRepeat(Animator animation) {

				}
			});
			//start animations
			animationOut.start();
			animationFadeIn.start();
		}
						

For the second if statement, we follow the same process, except this time we do the opposite animations. For this section of code, we want to move the menu back to off of the screen, fade the menu Text Views out, and fade the sideways Text View in. The only things that change are the animations that we call. Also, since we want the sideways text to reappear once the menu is back off of the screen, we want to fade the text in AFTER the menu animation is finished playing, instead of at the start. This is done in the onAnimationEnd() function of the menu's animation listener. We also make sure to update the state of the menu's animation with the boolean variable menuHidden,

//override the gesture(s) we want to use
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){

						..........
	
	//if x-velocity is to the left (negative)
	//and is more than our desired threshold
	//slide that menu off of the screen
	if((velocityX > 0) && !menuHidden){
		//add an update istener to the animator
		//so we can access the changing value
		animationPromptFadeIn.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				//grab the updated value
				int value = (int) animation.getAnimatedValue();
				//change text's opacity
				sidewaysText.setTextColor(Color.argb(value, 0, 0, 0));
			}
		});
		animationIn.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				//grab the updated value
				float value = (float) animation.getAnimatedValue();
				//put value into margin parameters object
				params.setMargins((int) value, 0, 0, 0);
				//set the new parameters object to the view's layout
				menu.setLayoutParams(params);
				//invalidate the view so that it is redrawn
				menu.invalidate();
			}
		});
		//we need to add a listener that triggers on the animation end
		animationIn.addListener(new Animator.AnimatorListener() {
			@Override
			public void onAnimationStart(Animator animation) {

			}

			@Override
			public void onAnimationEnd(Animator animation) {
				//set the menu state flag
				menuHidden = true;
				//start fading in sideways text
				animationPromptFadeIn.start();
			}

			@Override
			public void onAnimationCancel(Animator animation) {

			}

			@Override
			public void onAnimationRepeat(Animator animation) {

			}
		});
		//add an update listener to the animations that fade text
		animationFadeOut.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				//grab the updated value
				int value = (int) animation.getAnimatedValue();
				//use this value to change the alpha of the text
				menuHeader.setTextColor(Color.argb(value, 0, 0, 0));
				item1.setTextColor(Color.argb(value, 0, 0, 0));
				item2.setTextColor(Color.argb(value, 0, 0, 0));
				item3.setTextColor(Color.argb(value, 0, 0, 0));
			}
		});
		//start animation
		animationIn.start();
		animationFadeOut.start();
	}
	return true;
}
						

That's it! Now, you are ready to build and test your project either on an Android emulator provided through Android Studio, or even on your own Android device! To run the emulator, click the green play button near the top of the screen and choose your emulator. Your application should boot right up, and you will be able to swipe your menu on and off the screen and watch the animations play! Feel free to tweak any values you want, and play with the animations.





I hope you enjoyed this guide and were able to follow it! Now apply your knowledge of Touch Gestures and Animations to some awesome Android applications!