You are on page 1of 20

Introduction to animations

Animations can add visual cues that notify users about what's going on in your app.
They are especially useful when the UI changes state, such as when new content loads
or new actions become available. Animations also add a polished look to your app,
which gives it a higher quality look and feel.

Android includes different animation APIs depending on what type of animation you
want, so this page provides an overview of the different ways you can add motion to
your UI.

To better understand when you should use animations, also see the material design
guide to motion.

Animate bitmaps

An animated drawable

When you want to animate a bitmap graphic such as an icon or illustration, you should
use the drawable animation APIs. Usually, these animations are defined statically with a
drawable resource, but you can also define the animation behavior at runtime.

For example, animating a play button transforming into a pause button when tapped is a
nice way to communicate to the user that the two actions are related, and that pressing
one makes the other visible.

For more information, read Animate Drawable Graphics.

Animate UI visibility and motion

A subtle animation when a dialog appears and disappears makes the UI change less jarring

When you need to change the visibility or position of views in your layout, you should
include subtle animations to help the user understand how the UI is changing.

To move, reveal, or hide views within the current layout, you can use the property
animation system provided by the android.animation package, available in Android
3.0 (API level 11) and higher. These APIs update the properties of your View objects
over a period of time, continuously redrawing the view as the properties change. For
example, when you change the position properties, the view moves across the screen,
or when you change the alpha property, the view fades in or out.
To create these animations with the least amount of effort, you can enable animations
on your layout so that when you simply change the visibility of a view, an animation
applies automatically. For more information, see Auto Animate Layout Updates.

To learn how to build animations with the property animation system, read the Property
Animation Overview. Or see the following pages to create common animations:

 Change a view visibility with a crossfade


 Change a view visibility with a circular reveal
 Swap views with a card flip
 Change the view size with a zoom animation

Physics-based motion

Animation built with ObjectAnimator

Figure 4. Animation built with physics-based APIs

Whenever possible, your animations should apply real-world physics so they are
natural-looking. For example, they should maintain momentum when their target
changes, and make smooth transitions during any changes.

To provide these behaviors, the Android Support library includes physics-based


animation APIs that rely on the laws of physics to control how your animations occur.
Two common physics-based animations are the following:

 Spring Animation
 Fling Animation

Animations not based on physics—such as those built with ObjectAnimator APIs—are


fairly static and have a fixed duration. If the target value changes, you need to cancel
the animation at the time of target value change, re-configure the animation with a new
value as the new start value, and add the new target value. Visually, this process
creates an abrupt stop in the animation, and a disjointed movement afterwards, as
shown in figure 3.

Whereas, animations built by with physics-based animation APIs such


as DynamicAnimation are driven by force. The change in the target value results in a
change in force. The new force applies on the existing velocity, which makes a
continuous transition to the new target. This process results in a more natural-looking
animation, as shown in figure 4.

Animate layout changes

An animation to show more details can be achieved by either changing the layout or starting a new
activity

On Android 4.4 (API level 19) and higher, you can use the transition framework to
create animations when you swap the layout within the current activity or fragment. All
you need to do is specify the starting and ending layout, and what type of animation you
want to use. Then the system figures out and executes an animation between the two
layouts. You can use this to swap out the entire UI or to move/replace just some views.
For example, when the user taps an item to see more information, you can replace the
layout with the item details, applying a transition like the one shown in figure 5.

The starting and ending layout are each stored in a Scene, though the starting scene is
usually determined automatically from the current layout. You then create
a Transition to tell the system what type of animation you want, and then
call TransitionManager.go() and the system runs the animation to swap the layouts.

For more information, read Animate Between Layouts Using a Transition. And for
sample code, check out BasicTransition.

Animate between activities


On Android 5.0 (API level 21) and higher, you can also create animations that transition
between your activities. This is based on the same transition framework described
above to animate layout changes, but it allows you to create animations between
layouts in separate activities.

You can apply simple animations such as sliding the new activity in from the side or
fading it in, but you can also create animations that transition between shared views in
each activity. For example, when the user taps an item to see more information, you
can transition into a new activity with an animation that seamlessly grows that item to fill
the screen, like the animation shown in figure 5.

As usual, you call startActivity(), but pass it a bundle of options provided


by ActivityOptions.makeSceneTransitionAnimation(). This bundle of options
may include which views are shared between the activities so the transition framework
can connect them during the animation.

Drawables overview
When you need to display static images in your app, you can use the Drawable class
and its subclasses to draw shapes and images. A Drawable is a general abstraction
for something that can be drawn. The various subclasses help with specific image
scenarios, and you can extend them to define your own drawable objects that behave in
unique ways.

There are two ways to define and instantiate a Drawable besides using the class
constructors:

 Inflate an image resource (a bitmap file) saved in your project.


 Inflate an XML resource that defines the drawable properties.
Note: You might instead prefer using a vector drawable, which defines an image with a set of points,
lines, and curves, along with associated color information. This allows vector drawables to be scaled
for different sizes without a loss of quality. For more information, see Vector drawables overview.

Create drawables from resource images


You can add graphics to your app by referencing an image file from your project
resources. Supported file types are PNG (preferred), JPG (acceptable), and GIF
(discouraged). App icons, logos, and other graphics, such as those used in games, are
well suited for this technique.

To use an image resource, add your file to the res/drawable/ directory of your project.


Once in your project, you can reference the image resource from your code or your
XML layout. Either way, it's referred to using a resource ID, which is the file name
without the file type extension. For example, refer to my_image.png as my_image.

Note: Image resources placed in the res/drawable/ directory may be automatically optimized with


lossless image compression by the aapt tool during the build process. For example, a true-color
PNG that doesn't require more than 256 colors may be converted to an 8-bit PNG with a color
palette. This results in an image of equal quality but which requires less memory. As a result, the
image binaries placed in this directory can change at build time. If you plan on reading an image as
a bitstream in order to convert it to a bitmap, put your images in the res/raw/ folder instead, where
the aapt tool doesn't modify them.

The following code snippet demonstrates how to build an ImageView that uses an


image created from a drawable resource and adds it to the layout:

ConstraintLayout constraintLayout;

protected void onCreate(Bundle savedInstanceState) {


  super.onCreate(savedInstanceState);

  // Create a ConstraintLayout in which to add the ImageView


  constraintLayout = new ConstraintLayout(this);

  // Instantiate an ImageView and define its properties


  ImageView i = new ImageView(this);
  i.setImageResource(R.drawable.my_image);
 
i.setContentDescription(getResources().getString(R.string.my_image_desc));

  // set the ImageView bounds to match the Drawable's dimensions


  i.setAdjustViewBounds(true);
  i.setLayoutParams(new ViewGroup.LayoutParams(
          ViewGroup.LayoutParams.WRAP_CONTENT,
          ViewGroup.LayoutParams.WRAP_CONTENT));

  // Add the ImageView to the layout and set the layout as the content
view.
  constraintLayout.addView(i);
  setContentView(constraintLayout);
}

In other cases, you may want to handle your image resource as a Drawable object, as
shown in the following example:

Resources res = context.getResources();


Drawable myImage = ResourcesCompat.getDrawable(res, R.drawable.my_image,
null);

Note: Each unique resource in your project can maintain only one state, no matter how many
different objects you instantiate for it. For example, if you instantiate two Drawable objects from the
same image resource and change a property (such as the alpha) for one object, then it also affects
the other. When dealing with multiple instances of an image resource, instead of directly
transforming the Drawable object you should perform a tween animation.

The XML snippet below shows how to add a drawable resource to an ImageView in the
XML layout:

<ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/my_image"
        android:contentDescription="@string/my_image_desc" />

For more information about using project resources, see Resources and assets.

Note: When using image resources as the source of your drawables, be sure the images are the
appropriate size for various pixel densities. If the images are not correct they will be scaled up to fit,
which can cause artifacting in your drawables. For more information, read Support different pixel
densities.

Create drawables from XML resources


If there is a Drawable object that you'd like to create, which isn't initially dependent on
variables defined by your code or user interaction, then defining the Drawable in XML is
a good option. Even if you expect your Drawable to change its properties during the
user's interaction with your app, you should consider defining the object in XML, as you
can modify properties after it's instantiated.

After you've defined your Drawable in XML, save the file in


the res/drawable/ directory of your project. The following example shows the XML
that defines a TransitionDrawable resource, which inherits from Drawable:

<!-- res/drawable/expand_collapse.xml -->


<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/image_expand">
    <item android:drawable="@drawable/image_collapse">
</transition>

Then, retrieve and instantiate the object by calling Resources.getDrawable(), and


passing the resource ID of your XML file. Any Drawable subclass that supports
the inflate() method can be defined in XML and instantiated by your app. Each
drawable class that supports XML inflation utilizes specific XML attributes that help
define the object properties. The following code instantiates
the TransitionDrawable and sets it as the content of an ImageView object:

Resources res = context.getResources();


TransitionDrawable transition =
    (TransitionDrawable) ResourcesCompat.getDrawable(res,
R.drawable.expand_collapse, null);

ImageView image = (ImageView) findViewById(R.id.toggle_image);


image.setImageDrawable(transition);

// Description of the initial state that the drawable represents.


image.setContentDescription(getResources().getString(R.string.collapsed));

// Then you can call the TransitionDrawable object's methods.


transition.startTransition(1000);

// After the transition is complete, change the image's content


description
// to reflect the new state.

A layout defines the structure for a user interface in your app, such as in an activity. All
elements in the layout are built using a hierarchy of View and ViewGroup objects.
A View usually draws something the user can see and interact with. Whereas
a ViewGroup is an invisible container that defines the layout structure for View and
other ViewGroup objects, as shown in figure 1.

Figure 1. Illustration of a view hierarchy, which defines a UI layout

The View objects are usually called "widgets" and can be one of many subclasses, such
as Button or TextView. The ViewGroup objects are usually called "layouts" can be one
of many types that provide a different layout structure, such
as LinearLayout or ConstraintLayout .

You can declare a layout in two ways:

 Declare UI elements in XML. Android provides a straightforward XML vocabulary that


corresponds to the View classes and subclasses, such as those for widgets and layouts.

You can also use Android Studio's Layout Editor to build your XML layout using a drag-
and-drop interface.
 Instantiate layout elements at runtime. Your app can create View and ViewGroup
objects (and manipulate their properties) programmatically.

Declaring your UI in XML allows you to separate the presentation of your app from the
code that controls its behavior. Using XML files also makes it easy to provide different
layouts for different screen sizes and orientations (discussed further in Supporting
Different Screen Sizes).

The Android framework gives you the flexibility to use either or both of these methods to
build your app's UI. For example, you can declare your app's default layouts in XML,
and then modify the layout at runtime.

Tip:To debug your layout at runtime, use the Layout Inspector tool.

Write the XML


Using Android's XML vocabulary, you can quickly design UI layouts and the screen
elements they contain, in the same way you create web pages in HTML — with a series
of nested elements.

Each layout file must contain exactly one root element, which must be a View or
ViewGroup object. Once you've defined the root element, you can add additional layout
objects or widgets as child elements to gradually build a View hierarchy that defines
your layout. For example, here's an XML layout that uses a vertical LinearLayout to
hold a TextView and a Button:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

After you've declared your layout in XML, save the file with the .xml extension, in your
Android project's res/layout/ directory, so it will properly compile.

More information about the syntax for a layout XML file is available in the Layout
Resources document.

Load the XML Resource


When you compile your app, each XML layout file is compiled into a View resource. You
should load the layout resource from your app code, in
your Activity.onCreate() callback implementation. Do so by
calling setContentView(), passing it the reference to your layout resource in the form
of: R.layout.layout_file_name. For example, if your XML layout is saved
as main_layout.xml, you would load it for your Activity like so:

public void onCreate(Bundle savedInstanceState) {


    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

The onCreate() callback method in your Activity is called by the Android framework


when your Activity is launched (see the discussion about lifecycles, in
the Activities document).

Attributes
Every View and ViewGroup object supports their own variety of XML attributes. Some
attributes are specific to a View object (for example, TextView supports
the textSize attribute), but these attributes are also inherited by any View objects that
may extend this class. Some are common to all View objects, because they are
inherited from the root View class (like the id attribute). And, other attributes are
considered "layout parameters," which are attributes that describe certain layout
orientations of the View object, as defined by that object's parent ViewGroup object.

ID

Any View object may have an integer ID associated with it, to uniquely identify the View
within the tree. When the app is compiled, this ID is referenced as an integer, but the ID
is typically assigned in the layout XML file as a string, in the id attribute. This is an XML
attribute common to all View objects (defined by the View class) and you will use it very
often. The syntax for an ID, inside an XML tag is:

android:id="@+id/my_button"

The at-symbol (@) at the beginning of the string indicates that the XML parser should
parse and expand the rest of the ID string and identify it as an ID resource. The plus-
symbol (+) means that this is a new resource name that must be created and added to
our resources (in the R.java file). There are a number of other ID resources that are
offered by the Android framework. When referencing an Android resource ID, you do
not need the plus-symbol, but must add the android package namespace, like so:

android:id="@android:id/empty"

With the android package namespace in place, we're now referencing an ID from


the android.R resources class, rather than the local resources class.

In order to create views and reference them from the app, a common pattern is to:

1. Define a view/widget in the layout file and assign it a unique ID:

<Button android:id="@+id/my_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/my_button_text"/>

2. Then create an instance of the view object and capture it from the layout (typically in
the onCreate() method):

Button myButton = (Button) findViewById(R.id.my_button);

Defining IDs for view objects is important when creating a RelativeLayout. In a


relative layout, sibling views can define their layout relative to another sibling view,
which is referenced by the unique ID.

An ID need not be unique throughout the entire tree, but it should be unique within the
part of the tree you are searching (which may often be the entire tree, so it's best to be
completely unique when possible).

Note: With Android Studio 3.6 and higher, the view binding feature can


replace findViewById() calls and provides compile-time type safety for code that interacts with
views. Consider using view binding instead of findViewById().

Layout Parameters

XML layout attributes named layout_something define layout parameters for the View


that are appropriate for the ViewGroup in which it resides.

Every ViewGroup class implements a nested class that


extends ViewGroup.LayoutParams. This subclass contains property types that define
the size and position for each child view, as appropriate for the view group. As you can
see in figure 2, the parent view group defines layout parameters for each child view
(including the child view group).

Figure 2. Visualization of a view hierarchy with layout parameters associated with each view
Note that every LayoutParams subclass has its own syntax for setting values. Each
child element must define LayoutParams that are appropriate for its parent, though it
may also define different LayoutParams for its own children.

All view groups include a width and height ( layout_width and layout_height), and


each view is required to define them. Many LayoutParams also include optional margins
and borders.

You can specify width and height with exact measurements, though you probably won't
want to do this often. More often, you will use one of these constants to set the width or
height:

 wrap_content tells your view to size itself to the dimensions required by its content.
 match_parent tells your view to become as big as its parent view group will allow.

In general, specifying a layout width and height using absolute units such as pixels is
not recommended. Instead, using relative measurements such as density-independent
pixel units (dp), wrap_content, or match_parent, is a better approach, because it
helps ensure that your app will display properly across a variety of device screen sizes.
The accepted measurement types are defined in the Available Resources document.

Layout Position
The geometry of a view is that of a rectangle. A view has a location, expressed as a pair
of left and top coordinates, and two dimensions, expressed as a width and a height. The
unit for location and dimensions is the pixel.

It is possible to retrieve the location of a view by invoking the


methods getLeft() and getTop(). The former returns the left, or X, coordinate of the
rectangle representing the view. The latter returns the top, or Y, coordinate of the
rectangle representing the view. These methods both return the location of the view
relative to its parent. For instance, when getLeft() returns 20, that means the view is
located 20 pixels to the right of the left edge of its direct parent.

In addition, several convenience methods are offered to avoid unnecessary


computations, namely getRight() and getBottom(). These methods return the
coordinates of the right and bottom edges of the rectangle representing the view. For
instance, calling getRight() is similar to the following computation: getLeft() +
getWidth().

Size, Padding and Margins


The size of a view is expressed with a width and a height. A view actually possesses
two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions
define how big a view wants to be within its parent. The measured dimensions can be
obtained by calling getMeasuredWidth() and getMeasuredHeight().

The second pair is simply known as width and height, or sometimes drawing


width and drawing height. These dimensions define the actual size of the view on
screen, at drawing time and after layout. These values may, but do not have to, be
different from the measured width and height. The width and height can be obtained by
calling getWidth() and getHeight().

To measure its dimensions, a view takes into account its padding. The padding is
expressed in pixels for the left, top, right and bottom parts of the view. Padding can be
used to offset the content of the view by a specific number of pixels. For instance, a left
padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding
can be set using the setPadding(int, int, int, int) method and queried by
calling getPaddingLeft(), getPaddingTop(), getPaddingRight() and getPaddingB
ottom().

Even though a view can define a padding, it does not provide any support for margins.
However, view groups provide such a support. Refer
to ViewGroup and ViewGroup.MarginLayoutParams for further information.

For more information about dimensions, see Dimension Values.

Common Layouts
Each subclass of the ViewGroup class provides a unique way to display the views you
nest within it. Below are some of the more common layout types that are built into the
Android platform.

Note: Although you can nest one or more layouts within another layout to achieve your UI design,
you should strive to keep your layout hierarchy as shallow as possible. Your layout draws faster if it
has fewer nested layouts (a wide view hierarchy is better than a deep view hierarchy).

Linear Layout
A layout that organizes its children into a single horizontal or vertical row. It creates a
scrollbar if the length of the window exceeds the length of the screen.

Relative Layout

Enables you to specify the location of child objects relative to each other (child A to the
left of child B) or to the parent (aligned to the top of the parent).

Web View

Displays web pages.

Building Layouts with an Adapter


When the content for your layout is dynamic or not pre-determined, you can use a
layout that subclasses AdapterView to populate the layout with views at runtime. A
subclass of the AdapterView class uses an Adapter to bind data to its layout.
The Adapter behaves as a middleman between the data source and
the AdapterView layout—the Adapter retrieves the data (from a source such as an
array or a database query) and converts each entry into a view that can be added into
the AdapterView layout.

Common layouts backed by an adapter include:


List View

Displays a scrolling single column list.

Grid View

Displays a scrolling grid of columns and rows.

Filling an adapter view with data

You can populate an AdapterView such as ListView or GridView by binding


the AdapterView instance to an Adapter, which retrieves data from an external source
and creates a View that represents each data entry.

Android provides several subclasses of Adapter that are useful for retrieving different
kinds of data and building views for an AdapterView. The two most common adapters
are:

ArrayAdapter

Use this adapter when your data source is an array. By default, ArrayAdapter creates


a view for each array item by calling toString() on each item and placing the
contents in a TextView.

For example, if you have an array of strings you want to display in a ListView,
initialize a new ArrayAdapter using a constructor to specify the layout for each
string and the string array:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_list_item_1, myStringArray);

The arguments for this constructor are:

 Your app Context

 The layout that contains a TextView for each string in the array

 The string array

Then simply call setAdapter() on your ListView:

ListView listView = (ListView) findViewById(R.id.listview);


listView.setAdapter(adapter);

To customize the appearance of each item you can override


the toString() method for the objects in your array. Or, to create a view for
each item that's something other than a TextView (for example, if you want
an ImageView for each array item), extend the ArrayAdapter class and
override getView() to return the type of view you want for each item.

SimpleCursorAdapter

Use this adapter when your data comes from a Cursor. When
using SimpleCursorAdapter, you must specify a layout to use for each row in
the Cursor and which columns in the Cursor should be inserted into which views of
the layout. For example, if you want to create a list of people's names and phone
numbers, you can perform a query that returns a Cursor containing a row for each
person and columns for the names and numbers. You then create a string array
specifying which columns from the Cursor you want in the layout for each result and an
integer array specifying the corresponding views that each column should be placed:

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,


                       
ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
When you instantiate the SimpleCursorAdapter, pass the layout to use for each
result, the Cursor containing the results, and these two arrays:

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,


        R.layout.person_name_and_number, cursor, fromColumns,
toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);

The SimpleCursorAdapter then creates a view for each row in


the Cursor using the provided layout by inserting each fromColumns item into
the corresponding toViews view.
.

If, during the course of your app's life, you change the underlying data that is read by
your adapter, you should call notifyDataSetChanged(). This will notify the attached
view that the data has been changed and it should refresh itself.

Handling click events

You can respond to click events on each item in an AdapterView by implementing


the AdapterView.OnItemClickListener interface. For example:

// Create a message handling object as an anonymous class.


private OnItemClickListener messageClickedHandler = new
OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long
id) {
        // Do something in response to the click
    }
};

listView.setOnItemClickListener(messageClickedHandler);

Running Apps on Your Device


Overview
When building an Android app, it's important that you always test your application on a
real device in addition to emulators. This page describes how to set up your
development environment and Android-powered device for testing and debugging on
the device.

If you want an ideal SIM-unlocked phone to test on, then you might consider a Pixel
phone.

Connect your Phone to Computer


Plug in your device to your computer with a USB cable. If you're developing on
Windows, you might need to install this universal ADB USB driver or find your specific
USB driver for your device.

Enable USB Debugging


The next step is to enable USB debugging so your phone can interact with your
computer in a developer mode.
The following steps are needed:

1. (Windows Only) Install this ADB Driver


2. Plug-in your Android Device to Computer via USB
3. Open the "Settings" App on the Device
4. Scroll down to bottom to find "About phone" item
5. Scroll down to bottom to find "Build number" section
6. Tap on "Build Number" 7 times in quick succession
7. You should see the message "You are now a developer!"
8. Go back to main "Settings" page
9. Scroll down bottom to find "Developer options" item
10. Turn on "USB Debugging" switch and hit "OK"
11. Unplug and re-plug the device
12. Dialog appears "Allow USB Debugging?"
13. Check "Always allow from this computer" and then hit "OK"

Watch this video tutorial for a visual guide to getting USB debugging enabled.

Running your App


Now, we can launch apps from Android Studio onto our device:

1. Select one of your projects and click "Run" from the toolbar.
2. In the "Choose Device" window that appears, select the "Choose a running
device" radio button, select the device, and click OK.

Once Gradle finishes building, Android Studio should install the app on your connected
device and start it.

Troubleshooting
Not seeing your device in the "Choose Device" window? Try the following:

 Unplug your device from the USB port on the computer


 Restart the device by powering off and back on
 Verify that Settings => Developer options => USB Debugging  is enabled
 Quit and re-launch Android Studio
 Force restart ADB from the "Android Device Monitor"
 Plug your device back into the USB port on the computer
 Unlock the device and press "OK" on any dialog displayed

Now the phone should work as a debugging device as expected!

Still Not Working?


If after plugging the device into the computer and you don't see any message about
authorizing the device, then you may need to purchase another USB cable. Not all USB
cables are enabled for data transfer. If there's a chance that your cable may be a
charging only cable, you can purchase a USB-C cable for Pixel or the micro-USB cable
for Nexus 6 and prior.

What is the proper way of setting up an Android-powered device for app


development?
The following are steps to be followed prior to actual application development in an Android-
powered device:

  Declare your application as “debuggable” in your Android Manifest.


  Turn on “USB Debugging” on your device.
 Set up your system to detect your device.

You might also like