FlipCard animation using Fragments in Android.

By | August 17, 2013

Hello all

I am back with fragments again. I know you have seen a lot of posts on fragments and fragment animation.

This one will be another useful post for you.

This post helps you to show a FlipCard animation using Fragments.

Let us see how can we do this.

At first I will show the activity that I am using to create Animation which contain two fragments for Front and Back Page.

CardFlipActivity.java

[java]

package com.example.cardflipanimation;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.NavUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

public class CardFlipActivity extends Activity implements
FragmentManager.OnBackStackChangedListener {
/**
* A handler object, used for deferring UI operations.
*/
private Handler mHandler = new Handler();

/**
* Whether or not we’re showing the back of the card (otherwise showing the
* front).
*/
private boolean mShowingBack = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_card_flip);

if (savedInstanceState == null) {
// If there is no saved instance state, add a fragment representing
// the
// front of the card to this activity. If there is saved instance
// state,
// this fragment will have already been added to the activity.
getFragmentManager().beginTransaction()
.add(R.id.container, new CardFrontFragment()).commit();
} else {
mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
}

// Monitor back stack changes to ensure the action bar shows the
// appropriate
// button (either "photo" or "info").
getFragmentManager().addOnBackStackChangedListener(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);

// Add either a "photo" or "finish" button to the action bar, depending
// on which page
// is currently selected.
MenuItem item = menu.add(Menu.NONE, R.id.action_flip, Menu.NONE,
mShowingBack ? R.string.action_photo : R.string.action_info);
item.setIcon(mShowingBack ? R.drawable.ic_action_photo
: R.drawable.ic_action_info);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// Navigate "up" the demo structure to the launchpad activity.
// See http://developer.android.com/design/patterns/navigation.html
// for more.
NavUtils.navigateUpTo(this,
new Intent(this, CardFlipActivity.class));
return true;

case R.id.action_flip:
flipCard();
return true;
}

return super.onOptionsItemSelected(item);
}

private void flipCard() {
if (mShowingBack) {
getFragmentManager().popBackStack();
return;
}

// Flip to the back.

mShowingBack = true;

// Create and commit a new fragment transaction that adds the fragment
// for the back of
// the card, uses custom animations, and is part of the fragment
// manager’s back stack.

getFragmentManager().beginTransaction()

// Replace the default fragment animations with animator resources
// representing
// rotations when switching to the back of the card, as well as animator
// resources representing rotations when flipping back to the front
// (e.g. when
// the system Back button is pressed).
.setCustomAnimations(R.animator.card_flip_right_in,
R.animator.card_flip_right_out,
R.animator.card_flip_left_in,
R.animator.card_flip_left_out)

// Replace any fragments currently in the container view with a
// fragment
// representing the next page (indicated by the just-incremented
// currentPage
// variable).
.replace(R.id.container, new CardBackFragment())

// Add this transaction to the back stack, allowing users to
// press Back
// to get to the front of the card.
.addToBackStack(null)

// Commit the transaction.
.commit();

// Defer an invalidation of the options menu (on modern devices, the
// action bar). This
// can’t be done immediately because the transaction may not yet be
// committed. Commits
// are asynchronous in that they are posted to the main thread’s message
// loop.
mHandler.post(new Runnable() {
@Override
public void run() {
invalidateOptionsMenu();
}
});
}

@Override
public void onBackStackChanged() {
mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);

// When the back stack changes, invalidate the options menu (action
// bar).
invalidateOptionsMenu();
}

/**
* A fragment representing the front of the card.
*/
public static class CardFrontFragment extends Fragment {
public CardFrontFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_card_front, container,
false);
}
}

/**
* A fragment representing the back of the card.
*/
public static class CardBackFragment extends Fragment {
public CardBackFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_card_back, container,
false);
}
}
}
[/java]

Now the animations.
For that you have to create 4 xml animation files in the res/animator folder.

card_flip_left_in.xml
card_flip_left_out.xml
card_flip_right_in.xml
card_flip_right_out.xml

I will be listing these files in this order.

[xml]
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!– Before rotating, immediately set the alpha to 0. –>
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />

<!– Rotate. –>
<objectAnimator
android:valueFrom="-180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />

<!– Half-way through the rotation (see startOffset), set the alpha to 1. –>
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>

[/xml]

[xml]
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!– Rotate. –>
<objectAnimator android:valueFrom="0"
android:valueTo="180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full"></objectAnimator>

<!– Half-way through the rotation (see startOffset), set the alpha to 0. –>
<objectAnimator android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1"></objectAnimator>
</set>
[/xml]

[xml]
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!– Before rotating, immediately set the alpha to 0. –>
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />

<!– Rotate. –>
<objectAnimator
android:valueFrom="180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />

<!– Half-way through the rotation (see startOffset), set the alpha to 1. –>
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>

[/xml]

[xml]
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!– Rotate. –>
<objectAnimator
android:valueFrom="0"
android:valueTo="-180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />

<!– Half-way through the rotation (see startOffset), set the alpha to 0. –>
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>

[/xml]

Inside the drawable folder put these images.

ic_action_info.png
ic_action_photo.png
image1.png

Put these inside the ids.xml folder inside the res/values folder.

[xml]
<item type="id" name="action_next" />
<item type="id" name="action_flip" />
[/xml]

strings.xml
[xml]
<?xml version="1.0" encoding="utf-8"?>
<resources>

<string name="app_name">CardFlipAnimation</string>
<string name="hello_world">Hello world!</string>
<string name="menu_settings">Settings</string>
<string name="action_info">Photo info</string>
<string name="action_photo">View photo</string>

</resources>
[/xml]

And also integers.xml

[xml]
<resources>
<integer name="card_flip_time_full">300</integer>
<integer name="card_flip_time_half">150</integer>
</resources>
[/xml]

Download the complete android source code from here.