Tap the screen and watch the red disk move.
The white area is a
BackgroundView
object,
and the disk is a
LittleView
object.
(Actually, the
LittleView
is more than just the disc.
It is the square area that just barely encloses the disk.)
The
BackgroundView
imposes a size and initial position on the
LittleView
.
A
View
object has methods named
getX
and
setX
.
We summarize this by saying that a
View
object has a
property
named
x
.
Think of the property as a private field,
and the
getX
and
setX
as its getter and setter.
A
View
object has 12 properties that can be animated with a
ViewPropertyAnimator
:
property | getter | setter | animator | animator by |
---|---|---|---|---|
alpha |
getAlpha |
setAlpha |
alpha |
alphaBy |
rotation |
getRotation |
setRotation |
rotation |
rotationBy
|
rotationX |
getRotationX |
setRotationX |
rotationX |
rotationXBy
|
rotationY |
getRotationY |
setRotationY |
rotationY |
rotationYBy
|
scaleX |
setScaleX |
getScaleX |
scaleX |
scaleXBy |
scaleY |
setScaleY |
getScaleY |
scaleY |
scaleYBy |
translationX |
getTranslationX |
setTranslationX |
translationX |
translationXBy |
translationY |
getTranslationY |
setTranslationY |
translationY |
translationYBy |
translationZ |
getTranslationZ |
setTranslationZ |
translationZ |
translationZBy |
x |
getX |
setX |
x |
xBy |
y |
getY |
setY |
y |
yBy |
z |
getZ |
setZ |
z |
zBy |
The
BackgroundView
is touch sensitive because we plugged a
View.OnTouchListener
into it.
The
LittleView
moves because the
View.OnTouchListener
plugs a
ViewPropertyAnimator
into the
LittleView
.
The
ViewPropertyAnimator
gradually changes the
x
and
y
properties of the
LittleView
during a three-second interval.
(It changes
translationX
but not
getLeft
.)
See
Animating
with ViewPropertyAnimator
and
Introducing ViewPropertyAnimator.
MainActivity.java
BackgroundView
BackgroundView.java
.
Class
BackgroundView
calls
addView
,
so it must be a subclass of
ViewGroup
such as
RelativeLayout
.
Even though it is a
View
,
class
BackgroundView
does not need a
onDraw
method.
res/layout/sample_background_view.xml
res/values/attrs_background_view.xml
LittleView
LittleView.java
.
The
onLayout
method of the
LittleView
is called when the
LittleView
is created, and when the
BackgroundView
calls the
layout
method of the
LittleView
.
res/layout/sample_little_view.xml
res/values/attrs_little_view.xml
activity_main.xml
:
unused.
AndroidManifest.xml
build.gradle
(Module: app)
Create the two subclasses of class
View
named
BackgroundView
and
LittleView
.
Edit
BackgroundView.java
and change the superclass from
View
to
RelativeLayout
.
This is our first app to have more than one user-defined subclass of class
View
.
In the file
res/values/attrs_little_view.xml
,
rename the four
resources
to
exampleString1
,
exampleDimension1
,
etc.
This will remove the conflict with the four resources named
exampleString
,
exampleDimension
,
etc.,
in the file
res/values/attrs_background_view.xml
.
If you don’t rename the resources and you want to see the “Duplicate resources” error messages, click on Gradle Console in the lower right corner of Android Studio.
FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:mergeDebugResources'. > [attr/exampleColor] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_background_view.xml [attr/exampleColor] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_little_view.xml: Error: Duplicate resources [attr/exampleDimension] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_background_view.xml [attr/exampleDimension] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_little_view.xml: Error: Duplicate resources [attr/exampleDrawable] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_background_view.xml [attr/exampleDrawable] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_little_view.xml: Error: Duplicate resources [attr/exampleString] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_background_view.xml [attr/exampleString] /Users/myname/AndroidStudioProjects/ViewPropertyAnimator/app/src/main/res/values/attrs_little_view.xml: Error: Duplicate resources
onTouch
,
you can telescope
//Start two animations simultaneously. viewPropertyAnimator.x(newX); viewPropertyAnimator.y(newY);to
//Start two animations simultaneously. viewPropertyAnimator.x(newX).y(newY);
LittleView
green during the animation,
and change it back to red when the animation is over.
Add the following method to class
LittleView
.
public void setPaintColor(int color) { paint.setColor(color); }Insert an
Animator.AnimatorListener
into the
ViewPropertyAnimator
before starting the animations.
An
AnimatorListenerAdapter
is an
Animator.AnimatorListener
with all of its methods implemented as stubs.
This means that we have to override only the two methods we’re
interested in overriding,
not all four of them.
viewPropertyAnimator.setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { littleView.setPaintColor(Color.GREEN); littleView.invalidate(); } @Override public void onAnimationEnd(Animator animation) { littleView.setPaintColor(Color.RED); littleView.invalidate(); } });
LittleView
fade out during the first animation.
Change
//Start two animations simultaneously. viewPropertyAnimator.x(newX).y(newY);to
//Start three animations simultaneously. viewPropertyAnimator.x(newX).y(newY).alpha(0f);If you think it’s clearer, you can write it as three separate statements:
//Start three animations simultaneously. viewPropertyAnimator.x(newX); viewPropertyAnimator.y(newY); viewPropertyAnimator.alpha(0f);Change the orientation of the device to destroy and re-create the
Activity
object,
which will destroy and re-create the
View
s with their default alphas.
LittleView
grow during the first animation.
Change
//Start two animations simultaneously. viewPropertyAnimator.x(newX).y(newY);to
//Start four animations simultaneously. viewPropertyAnimator.x(newX).y(newY).scaleX(2f).scaleY(2f);
LittleView
grow a bit during each animation.
Shorten the duration for a snappier animation.
Tap the center of the disk.
//Start four animations simultaneously. viewPropertyAnimator.x(newX).y(newY).scaleXBy(.1f).scaleYBy(.1f);
LittleView
a dashed outline so we can see that it’s really a square.
Each dash is 10 pixels long, followed by a five pixel gap.
//an additional field for class LittleView private Paint outlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//in the LittleView constructor outlinePaint.setColor(Color.BLACK); outlinePaint.setStyle(Paint.Style.STROKE); //vs. FILL outlinePaint.setStrokeWidth(0f); //0f for hairline (1 pixel) DashPathEffect dashPathEffect = new DashPathEffect(new float[] {10f, 5f}, 0f); outlinePaint.setPathEffect(dashPathEffect);
//in the LittleView onDraw, immediately before the translate Rect outline = canvas.getClipBounds(); //the rectangular boundary of the canvas canvas.drawRect(outline, outlinePaint);
LittleView
is really a square,
make it
tumble during each animation.
//Start three animations simultaneously. viewPropertyAnimator.x(newX).y(newY).rotationBy(45f); //degrees clockwise
LittleView
in three dimensions around its vertical axis (the Y axis).
Its left edge will move towards you,
and its right edge away.
//Start three animations simultaneously. viewPropertyAnimator.x(newX).y(newY).rotationYBy(180f); //counterclockwise when viewed from above