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
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); } } }
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.
<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>
<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>
<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>
<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>
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.
<item type="id" name="action_next" /> <item type="id" name="action_flip" />
strings.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>
And also integers.xml
<resources> <integer name="card_flip_time_full">300</integer> <integer name="card_flip_time_half">150</integer> </resources>
Download the complete android source code from here.