Tap on the screen to move the red disk.
The entire screen,
including the white background and the red disk,
is one big object of class
MyView
.
The disk is not an object at all.
It is drawn by a call to
drawCircle
in the
onDraw
method of the
MyView
.
The
MyView
contains a field named
center
of class
PointF
,
holding the coördinates of the center of the disk.
When you tap the screen,
we create an
ObjectAnimator
object that gradually changes the vaue of this property
from its current value to the point where the finger touched.
During the animation,
the
ObjectAnimator
repeatedly calls the
evaluate
method of the
TypeEvaluator
object
and the
setCenter
setter for the
center
field.
See
Animating
with ObjectAnimator
and
Using
a Type Evaluator.
If the property to be animated is an object
(e.g., a
PointF
),
the fourth argument of
ObjectAnimator.ofObject
must be a copy of the property.
If the fourth argument
were missing,
the
ObjectAnimator
would also attempt to call a
getCenter
getter.
In this case, an obscure bug would happen.
The
startValue
passed to
evaluate
would constantly be updated to be the
current
value of the field,
causing the field to reach its final value too soon.
The
Animation
app had a
TranslateAnimation
(SDK 1,
subclass of
Animation
).
This app has an
ObjectAnimator
(SDK 11,
subclass of
Animator
).
The previous app didn’t change the properties
(x
and
y
)
of the moving drawable until the animation was finished.
This app changes the properties while the animation is in progress,
which makes more sense.
MainActivity.java
MyView.java
activity_main.xml
:
unused.
AndroidManifest.xml
:
untouched.
build.gradle
(Module: app)
app/java/com.example.android.apis/animation/BouncingBalls.java
BouncingBalls
is a subclass of class
Activity
.
It creates eight
ObjectAnimator
s.
The first one,
colorAnim
,
uses an
ArgbEvaluator
instead of our
PointFEvaluator
.
The remaining
ObjectAnimator
s
do not need any
TypeEvauator
objects at all,
because the fields they animate are merely of type
float
.
To make the animations happen one after another,
the
BouncingBalls.MyAnimationView
object also puts five of the animations in an
AnimatorSet
,
and two of them in another
AnimatorSet
.
app/java/com.example.android.apis/animation/ShapeHolder.java
ShapeHolder
contains a
ShapeDrawable
,
which is a subclass of
Drawable
.
app/res/layout/bouncing_balls.xml
LinearLayout
whose
id
is
container
.
app/java/com.example.android.apis/animation/AnimationCloning.java
AnimationCloning
is a subclass of class
Activity
.
Its nested class
AnimationCloning.MyAnimationView
creates four
ObjectAnimator
s.
app/java/com.example.android.apis/animation/ShapeHolder.java
ShapeHolder
contains a
ShapeDrawable
,
which is a subclass of
Drawable
.
app/res/layout/animation_cloning.xml
Button
in a
LinearLayout
.
app/java/com.example.android.apis/animation/CustomEvaluator.java
CustomEvaluator
is a subclass of class
Activity
.
Its nested class
CustomEvaluator.XYHolder
is just like Android’s class
PointF
,
and its nested class
CustomEvaluator.XYEvaluator
is just like our class
PointFEvaluator
.
app/java/com.example.android.apis/animation/ShapeHolder.java
ShapeHolder
contains a
ShapeDrawable
,
which is a subclass of
Drawable
.
app/res/layout/animator_custom_evaluator.xml
Button
.
ObjectAnimator
’s
interpolator to
AccelerateDecelerateInterpolator
(the default).
objectAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animator) { Toast.makeText(getContext(), "onAnimationEnd", Toast.LENGTH_LONG).show(); } });
backgroundColor
of the
MyView
instead of its
center
.
Replace the
ObjectAnimator
with the following.
You can remove class
PointFEvaluator
.
ObjectAnimator objectAnimator = ObjectAnimator.ofInt( MyView.this, "backgroundColor", Color.YELLOW //end value ); objectAnimator.setEvaluator(new ArgbEvaluator()); objectAnimator.setDuration(1000L); //milliseconds objectAnimator.start();Change the orientation of the device (portrait to landscape) to destroy and re-create the
Activity
object, and with it the
MyView
object.
backgroundColor
and
center
of the
MyView
simultaneously.
Replace the
ObjectAnimator
with the following.
ObjectAnimator centerAnimator = ObjectAnimator.ofObject( MyView.this, "center", //name of field new PointFEvaluator(), new PointF(center.x, center.y), //start value new PointF(motionEvent.getX(), motionEvent.getY()) //end value ); ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofInt( MyView.this, "backgroundColor", Color.YELLOW //end value ); backgroundColorAnimator.setEvaluator(new ArgbEvaluator()); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.setDuration(3000L); //milliseconds animatorSet.playTogether(centerAnimator, backgroundColorAnimator); animatorSet.start();
AnimatorSet animatorSet = new AnimatorSet(); animatorSet.setDuration(3000L); //milliseconds animatorSet.playSequentially(centerAnimator, backgroundColorAnimator); animatorSet.start();