In this post we are going to look at how to create a 3D flip animation, with a FrameLayout.
In the first few posts I've written on Android and animations we have only looked at the predefined animations supplied in the android.view.animationspackage. In fact we've only used the translate animation, but as I've mentioned before there are also rotate, scale and alpha animations.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
2.
<
FrameLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
3.
android:id
=
"@+id/container"
4.
android:layout_width
=
"fill_parent"
5.
android:layout_height
=
"fill_parent"
>
6.
<
include
android:id
=
"@+id/notelist"
layout
=
"@layout/first_view"
/>
7.
<
include
android:id
=
"@+id/notelist"
layout
=
"@layout/second_view"
/>
8.
</
FrameLayout
>
<
RelativeLayout
android:id
=
"@+id/Layout01"
02.
android:layout_width
=
"fill_parent"
03.
android:layout_height
=
"fill_parent"
04.
xmlns:android
=
"http://schemas.android.com/apk/res/android"
>
05.
<
mageView
06.
android:layout_centerHorizontal
=
"true"
07.
android:layout_centerVertical
=
"true"
08.
android:layout_width
=
"wrap_content"
09.
android:id
=
"@+id/ImageView01"
10.
android:layout_height
=
"wrap_content"
11.
android:src
=
"@drawable/firefox"
12.
>
13.
</
ImageView
>
14.
</
RelativeLayout
>
<
RelativeLayout
android:id
=
"@+id/Layout02"
02.
android:layout_width
=
"fill_parent"
03.
android:layout_height
=
"fill_parent"
04.
xmlns:android
=
"http://schemas.android.com/apk/res/android"
>
05.
<
ImageView
06.
android:layout_centerHorizontal
=
"true"
07.
android:layout_centerVertical
=
"true"
08.
android:layout_width
=
"wrap_content"
09.
android:id
=
"@+id/ImageView02"
10.
android:layout_height
=
"wrap_content"
11.
android:src
=
"@drawable/firefox_alt"
12.
>
13.
</
ImageView
>
14.
</
RelativeLayout
>
These two views are almost identical and only contain two different images that we will flip between.Now we have our layouts defined we need to write some Java to implement our 3d flip. Create a Java class called Flip3dAnimation in the com.example.flip3d package and cut and paste in this code:
package
com.example.flip3d;
02.
03.
import
android.graphics.Camera;
04.
import
android.graphics.Matrix;
05.
import
android.view.animation.Animation;
06.
import
android.view.animation.Transformation;
07.
08.
public
class
Flip3dAnimation
extends
Animation {
09.
private
final
float
mFromDegrees;
10.
private
final
float
mToDegrees;
11.
private
final
float
mCenterX;
12.
private
final
float
mCenterY;
13.
private
Camera mCamera;
14.
15.
public
Flip3dAnimation(
float
fromDegrees,
float
toDegrees,
16.
float
centerX,
float
centerY) {
17.
mFromDegrees = fromDegrees;
18.
mToDegrees = toDegrees;
19.
mCenterX = centerX;
20.
mCenterY = centerY;
21.
}
22.
23.
@Override
24.
public
void
initialize(
int
width,
int
height,
int
parentWidth,
int
parentHeight) {
25.
super
.initialize(width, height, parentWidth, parentHeight);
26.
mCamera =
new
Camera();
27.
}
28.
29.
@Override
30.
protected
void
applyTransformation(
float
interpolatedTime, Transformation t) {
31.
final
float
fromDegrees = mFromDegrees;
32.
float
degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
33.
34.
final
float
centerX = mCenterX;
35.
final
float
centerY = mCenterY;
36.
final
Camera camera = mCamera;
37.
38.
final
Matrix matrix = t.getMatrix();
39.
40.
camera.save();
41.
42.
camera.rotateY(degrees);
43.
44.
camera.getMatrix(matrix);
45.
camera.restore();
46.
47.
matrix.preTranslate(-centerX, -centerY);
48.
matrix.postTranslate(centerX, centerY);
49.
50.
}
51.
}
Get the tranformation matrix for the Animation
Generate a rotation matrix using camera.rotate(degrees)
Apply that matrix to the Animation transform
Set a pre translate so that the view is moved to the edge of the screen and rotates around it centre and not it's edge
Set a post translate so that the animated view is placed back in the centre of the screen.
package
com.example.flip3d;
02.
03.
import
android.app.Activity;
04.
import
android.os.Bundle;
05.
import
android.view.View;
06.
import
android.view.animation.AccelerateInterpolator;
07.
import
android.widget.ImageView;
08.
09.
public
class
Flip3d
extends
Activity {
10.
11.
12.
private
ImageView image1;
13.
private
ImageView image2;
14.
15.
private
boolean
isFirstImage =
true
;
16.
17.
18.
/** Called when the activity is first created. */
19.
@Override
20.
public
void
onCreate(Bundle savedInstanceState) {
21.
super
.onCreate(savedInstanceState);
22.
setContentView(R.layout.main);
23.
24.
image1 = (ImageView) findViewById(R.id.ImageView01);
25.
image2 = (ImageView) findViewById(R.id.ImageView02);
26.
image2.setVisibility(View.GONE);
27.
28.
image1.setOnClickListener(
new
View.OnClickListener() {
29.
public
void
onClick(View view) {
30.
if
(isFirstImage) {
31.
applyRotation(
0
,
90
);
32.
isFirstImage = !isFirstImage;
33.
34.
}
else
{
35.
applyRotation(
0
, -
90
);
36.
isFirstImage = !isFirstImage;
37.
}
38.
}
39.
});
40.
}
41.
42.
private
void
applyRotation(
float
start,
float
end) {
43.
// Find the center of image
44.
final
float
centerX = image1.getWidth() /
2
.0f;
45.
final
float
centerY = image1.getHeight() /
2
.0f;
46.
47.
// Create a new 3D rotation with the supplied parameter
48.
// The animation listener is used to trigger the next animation
49.
final
Flip3dAnimation rotation =
50.
new
Flip3dAnimation(start, end, centerX, centerY);
51.
rotation.setDuration(
500
);
52.
rotation.setFillAfter(
true
);
53.
rotation.setInterpolator(
new
AccelerateInterpolator());
54.
rotation.setAnimationListener(
new
DisplayNextView(isFirstImage, image1, image2));
55.
56.
if
(isFirstImage)
57.
{
58.
image1.startAnimation(rotation);
59.
}
else
{
60.
image2.startAnimation(rotation);
61.
}
62.
63.
}
64.
}
package
com.example.flip3d;
02.
03.
import
android.view.animation.Animation;
04.
import
android.widget.ImageView;
05.
06.
public
final
class
DisplayNextView
implements
Animation.AnimationListener {
07.
private
boolean
mCurrentView;
08.
ImageView image1;
09.
ImageView image2;
10.
11.
public
DisplayNextView(
boolean
currentView, ImageView image1, ImageView image2) {
12.
mCurrentView = currentView;
13.
this
.image1 = image1;
14.
this
.image2 = image2;
15.
}
16.
17.
public
void
onAnimationStart(Animation animation) {
18.
}
19.
20.
public
void
onAnimationEnd(Animation animation) {
21.
image1.post(
new
SwapViews(mCurrentView, image1, image2));
22.
}
23.
24.
public
void
onAnimationRepeat(Animation animation) {
25.
}
26.
}
package
com.example.flip3d;
02.
03.
import
android.view.View;
04.
import
android.view.animation.DecelerateInterpolator;
05.
import
android.widget.ImageView;
06.
07.
public
final
class
SwapViews
implements
Runnable {
08.
private
boolean
mIsFirstView;
09.
ImageView image1;
10.
ImageView image2;
11.
12.
public
SwapViews(
boolean
isFirstView, ImageView image1, ImageView image2) {
13.
mIsFirstView = isFirstView;
14.
this
.image1 = image1;
15.
this
.image2 = image2;
16.
}
17.
18.
public
void
run() {
19.
final
float
centerX = image1.getWidth() /
2
.0f;
20.
final
float
centerY = image1.getHeight() /
2
.0f;
21.
Flip3dAnimation rotation;
22.
23.
if
(mIsFirstView) {
24.
image1.setVisibility(View.GONE);
25.
image2.setVisibility(View.VISIBLE);
26.
image2.requestFocus();
27.
28.
rotation =
new
Flip3dAnimation(-
90
,
0
, centerX, centerY);
29.
}
else
{
30.
image2.setVisibility(View.GONE);
31.
image1.setVisibility(View.VISIBLE);
32.
image1.requestFocus();
33.
34.
rotation =
new
Flip3dAnimation(
90
,
0
, centerX, centerY);
35.
}
36.
37.
rotation.setDuration(
500
);
38.
rotation.setFillAfter(
true
);
39.
rotation.setInterpolator(
new
DecelerateInterpolator());
40.
41.
if
(mIsFirstView) {
42.
image2.startAnimation(rotation);
43.
}
else
{
44.
image1.startAnimation(rotation);
45.
}
46.
}
47.
}