We will be playing with android's gorgeous new Material Design theme. We will be covering the following material widgets and animations that were introduced in Android 5.0 (API level 21).
- RecyclerView (the new ListView)
- CardView (custom outline and shadow)
- Ripple Animation (touch feedback)
- Palette (incorporate dynamic color)
- Shared Element Activity Transition
- Floating Action Button
- Circular Reveal Animation
Review Material Design Primer for a more detailed overview of all aspects of a material designed app.
Make sure you are working with a device or emulator running on API 21 or higher. While support libraries are available for material views and widgets, none of the animations would work on API versions lower than 21. Android introduced a dedicated render thread with API 21 for many of the Material Design animations, so they don't hold up the primary UI thread. At this moment it is not possible to work with Material Design animations on API versions lower than 21 due to the absence of this render thread.
- Import base app
-
The app loads a list of contacts into a
RecyclerView
where each list item is represented by aCardView
. You will be building new features on top of this app. -
Clone android-lollipop-exercise repo on your machine. Import the project in Android Studio:
- Test your app
-
Test to verify that the app runs without any errors.
-
If your app loads successfully, you should see the following output:
- Understand existing code
- The app uses two new widgets that were introduced in API 21:
RecyclerView
andCardView
. - Make sure you understand these concepts before moving forward.
- Refer to Using the RecyclerView cliffnotes for more information on
RecyclerView
. - Refer to Using the CardView cliffnotes for detailed guide on using a
CardView
.
- Hook up Detail View
- You will find
DetailsActivity.java
and it's layout fileactivity_details.xml
in your project to display more information about the contact selected from the list.- This activity is used to show contact's profile picture, name and phone number.
- The item click listener for the contacts list can be found inside the static internal class
VH
ofContactsAdapter.java
. - Fire an intent when the user selects a contact from the list.
- Pass the contact through the intent and populate the detail view.
- Refer to the Using Intents to Create Flows cliffnotes for guidelines on passing data between activities.
- Test your app
-
If you run your app and click on a contact from the list, you should be able to view the detail view.
- Add Ripple Animation
- Add touch feedback animation, also called as 'ripple effect' to the
CardView
to provide visual effect to the user when an item in the list is touched. - Refer to the Adding Ripple Effect cliffnotes for guidelines.
- Read more about touch animations in Ripple Animations cliffnotes.
- Test your app
-
You should see the following output if you run your app now. Notice the ripple effect when you click on a list item.
- Use Palette
-
Use the new
Palette
API to extract the most vibrant color from the contact's profile image . -
Use this color to set the background color of the
R.id.vPalette
view containing contact's name inContactsActivity
andDetailsActivity
. -
The
Palette
API requires a bitmap of the image you want to extract the colors from as a parameter. You can usePicasso
to get a callback with a bitmap, which can then be used to extract the most vibrant color from thePalette
. -
In
ContactsAdapter.java
andDetailsActivity.java
, you'll need to change the way the profile image is being loaded into theImageView
as follows:// Make sure to import this line at the top! import com.squareup.picasso.Target; // Use Picasso to get a callback with a Bitmap which can then // be used to extract a vibrant color from the Palette. // Define a listener for image loading Target target = new Target() { // Fires when Picasso finishes loading the bitmap for the target @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { // TODO 1. Insert the bitmap into the profile image view // TODO 2. Use generateAsync() method from the Palette API to get the vibrant color from the bitmap // Set the result as the background color for `R.id.vPalette` view containing the contact's name. } // Fires if bitmap fails to load @Override public void onBitmapFailed(Drawable errorDrawable) { } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } }; // Store the target into the tag for the profile to ensure target isn't garbage collected prematurely holder.ivProfile.setTag(target); // Instruct Picasso to load the bitmap into the target defined above Picasso.with(mContext).load(contact.getThumbnailDrawable()).into(target);
-
See the Dynamic Color using Palette cliffnotes for guidelines on using the
Palette
API.
- Test your app
-
If you were able to successfully extract the vibrant color from the profile image using the
Palette
API to set the background color of your views, you should see the following output:
- Implement Shared Element Activity Transition
- A shared element transition determines how shared element views—also called hero views are animated from one activity to another during a scene transition. Shared element transitions are governed by changes to each shared element view's position, size, and appearance.
- Add shared element activity transition to provide a seamless experience by emphasizing continuity between activity transitions.
ContactsActivity
andDetailsActivity
share three views:ivProfile
,vPalette
andtvName
.- Animate these three views while transitioning from
ContactsActivity
toDetailsActivity
and vice versa. - Refer to the Shared Element Activity Transition cliffnotes for guidelines on implementing hero transitions.
- Test your app
- Add Floating Action Button
-
Add a floating action button to
DetailsActivity
to dial a phone call to the selected contact. -
Floating action buttons are used for a special type of promoted action. They are distinguished by a circled icon floating above the UI.
-
The floating action button should be placed 16dp min from the edge on mobile and 24dp min on tablet/desktop.
-
Use the support libraries FloatingActionButton to add a button.
-
First, make sure that the library has been added to your
build.gradle
file. -
Next, add the custom
FloatingActionButton
view to youractivity_details.xml
layout file as follows:<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> ... <FrameLayout xmlns:fab="http://schemas.android.com/apk/res-auto" android:layout_below="@+id/ivProfile" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginTop="-50dp"> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:src="@drawable/ic_call" app:fabSize="normal" android:visibility="invisible" android:layout_gravity="bottom|right" android:layout_margin="16dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </FrameLayout> </RelativeLayout>
-
Extract the floating action button in your
DetailsActivity.java
file as follows:private FloatingActionButton fab; @Override protected void onCreate(Bundle savedInstanceState) { // ... fab = (FloatingActionButton) findViewById(R.id.fab); // ... }
-
See the floating action button guide for more details.
- Setup Click Listener
-
Setup a click listener on the fab button within your activity and dial the person's number on click of the button using an implicit intent.
@Override protected void onCreate(Bundle savedInstanceState) { // ... // Extract FAB fab = (FloatingActionButton) findViewById(R.id.fab); // Dial contact's number. // This shows the dialer with the number, allowing you to explicitly initiate the call. fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String uri = "tel:" + mContact.getNumber(); Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse(uri)); startActivity(intent); } }); // ... }
- Test your app
- Enable Up Button on
ActionBar
-
The navigation button or the up button appears in the
ActionBar
alongside the activity title. -
In
DetailsActivity.java
, enable up button by including below code:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); // Enable up button getSupportActionBar().setDisplayHomeAsUpEnabled(true); // ... }
- Add Circular Reveal Animation
-
Add circular reveal animation effect on the floating action button so that the button is revealed while entering the activity. Reverse this transition while exiting the activity.
-
When the activity starts, you would be revealing a previously invisible view. Hide your button in the
onCreate()
method before starting the animation to make the animation look right.fab.setVisibility(View.INVISIBLE);
or in xml with
android:visibility="invisible"
-
Follow Circular Reveal Animation cliffnotes to add
enterReveal()
andexitReveal()
transitions on the floating action button. -
Make sure to enable exit reveal transition on press of
ActionBar
up button or back button, callexitReveal()
fromonOptionsItemSelected()
andonBackPressed()
as mentioned in the guide.
- Test your app