Add PathAnimations ApiDemos.
Change-Id: I9b064032cd503450ba6d8c93453a4ab6c2163686
This commit is contained in:
@@ -1419,6 +1419,15 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name=".animation.PathAnimations"
|
||||||
|
android:label="Animation/Path Animations"
|
||||||
|
android:enabled="@bool/atLeastHoneycomb">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.SAMPLE_CODE" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<!-- ************************************* -->
|
<!-- ************************************* -->
|
||||||
<!-- ANIMATION PACKAGE SAMPLES -->
|
<!-- ANIMATION PACKAGE SAMPLES -->
|
||||||
<!-- ************************************* -->
|
<!-- ************************************* -->
|
||||||
|
|||||||
50
samples/ApiDemos/res/layout/path_animations.xml
Normal file
50
samples/ApiDemos/res/layout/path_animations.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<ScrollView android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<RadioGroup android:orientation="horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/path_animation_type"
|
||||||
|
>
|
||||||
|
<RadioButton android:id="@+id/named_components"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Named Components"/>
|
||||||
|
<RadioButton android:id="@+id/property_components"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Property Components"/>
|
||||||
|
<RadioButton android:id="@+id/multi_int"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Multi-int"/>
|
||||||
|
<RadioButton android:id="@+id/multi_float"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Multi-float"/>
|
||||||
|
<RadioButton android:id="@+id/named_setter"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Named Property"/>
|
||||||
|
<RadioButton android:id="@+id/property_setter"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Property"/>
|
||||||
|
</RadioGroup>
|
||||||
|
</ScrollView>
|
||||||
|
<view class="com.example.android.apis.animation.PathAnimations$CanvasView"
|
||||||
|
android:id="@+id/canvas"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0px"
|
||||||
|
android:layout_weight="1">
|
||||||
|
<ImageView android:id="@+id/moved_item"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/frog"/>
|
||||||
|
</view>
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.android.apis.animation;
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.animation.TypeConverter;
|
||||||
|
import android.animation.ValueAnimator;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.PointF;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.FloatMath;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Property;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.LinearInterpolator;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
|
|
||||||
|
import com.example.android.apis.R;
|
||||||
|
|
||||||
|
/** This application demonstrates the use of Path animation. */
|
||||||
|
public class PathAnimations extends Activity implements
|
||||||
|
RadioGroup.OnCheckedChangeListener, View.OnLayoutChangeListener {
|
||||||
|
|
||||||
|
final static Path sTraversalPath = new Path();
|
||||||
|
final static float TRAVERSE_PATH_SIZE = 7.0f;
|
||||||
|
|
||||||
|
final static Property<PathAnimations, Point> POINT_PROPERTY
|
||||||
|
= new Property<PathAnimations, Point>(Point.class, "point") {
|
||||||
|
@Override
|
||||||
|
public Point get(PathAnimations object) {
|
||||||
|
View v = object.findViewById(R.id.moved_item);
|
||||||
|
return new Point(Math.round(v.getX()), Math.round(v.getY()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(PathAnimations object, Point value) {
|
||||||
|
object.setCoordinates(value.x, value.y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static {
|
||||||
|
float inverse_sqrt8 = FloatMath.sqrt(0.125f);
|
||||||
|
RectF bounds = new RectF(1, 1, 3, 3);
|
||||||
|
sTraversalPath.addArc(bounds, 45, 180);
|
||||||
|
sTraversalPath.addArc(bounds, 225, 180);
|
||||||
|
|
||||||
|
bounds.set(1.5f + inverse_sqrt8, 1.5f + inverse_sqrt8, 2.5f + inverse_sqrt8,
|
||||||
|
2.5f + inverse_sqrt8);
|
||||||
|
sTraversalPath.addArc(bounds, 45, 180);
|
||||||
|
sTraversalPath.addArc(bounds, 225, 180);
|
||||||
|
|
||||||
|
bounds.set(4, 1, 6, 3);
|
||||||
|
sTraversalPath.addArc(bounds, 135, -180);
|
||||||
|
sTraversalPath.addArc(bounds, -45, -180);
|
||||||
|
|
||||||
|
bounds.set(4.5f - inverse_sqrt8, 1.5f + inverse_sqrt8, 5.5f - inverse_sqrt8, 2.5f + inverse_sqrt8);
|
||||||
|
sTraversalPath.addArc(bounds, 135, -180);
|
||||||
|
sTraversalPath.addArc(bounds, -45, -180);
|
||||||
|
|
||||||
|
sTraversalPath.addCircle(3.5f, 3.5f, 0.5f, Path.Direction.CCW);
|
||||||
|
|
||||||
|
sTraversalPath.addArc(new RectF(1, 2, 6, 6), 0, 180);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CanvasView mCanvasView;
|
||||||
|
|
||||||
|
private ObjectAnimator mAnimator;
|
||||||
|
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.path_animations);
|
||||||
|
mCanvasView = (CanvasView) findViewById(R.id.canvas);
|
||||||
|
mCanvasView.addOnLayoutChangeListener(this);
|
||||||
|
((RadioGroup) findViewById(R.id.path_animation_type)).setOnCheckedChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCoordinates(int x, int y) {
|
||||||
|
changeCoordinates((float) x, (float) y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeCoordinates(float x, float y) {
|
||||||
|
View v = findViewById(R.id.moved_item);
|
||||||
|
v.setX(x);
|
||||||
|
v.setY(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPoint(PointF point) {
|
||||||
|
changeCoordinates(point.x, point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
startAnimator(checkedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
|
||||||
|
int oldTop, int oldRight, int oldBottom) {
|
||||||
|
int checkedId = ((RadioGroup)findViewById(R.id.path_animation_type)).getCheckedRadioButtonId();
|
||||||
|
if (checkedId != RadioGroup.NO_ID) {
|
||||||
|
startAnimator(checkedId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startAnimator(int checkedId) {
|
||||||
|
if (mAnimator != null) {
|
||||||
|
mAnimator.cancel();
|
||||||
|
mAnimator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
View view = findViewById(R.id.moved_item);
|
||||||
|
Path path = mCanvasView.getPath();
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (checkedId) {
|
||||||
|
case R.id.named_components:
|
||||||
|
// Use the named "x" and "y" properties for individual (x, y)
|
||||||
|
// coordinates of the Path and set them on the view object.
|
||||||
|
// The setX(float) and setY(float) methods are called on view.
|
||||||
|
// An int version of this method also exists for animating
|
||||||
|
// int Properties.
|
||||||
|
mAnimator = ObjectAnimator.ofFloat(view, "x", "y", path);
|
||||||
|
break;
|
||||||
|
case R.id.property_components:
|
||||||
|
// Use two Properties for individual (x, y) coordinates of the Path
|
||||||
|
// and set them on the view object.
|
||||||
|
// An int version of this method also exists for animating
|
||||||
|
// int Properties.
|
||||||
|
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
|
||||||
|
break;
|
||||||
|
case R.id.multi_int:
|
||||||
|
// Use a multi-int setter to animate along a Path. The method
|
||||||
|
// setCoordinates(int x, int y) is called on this during the animation.
|
||||||
|
// Either "setCoordinates" or "coordinates" are acceptable parameters
|
||||||
|
// because the "set" can be implied.
|
||||||
|
mAnimator = ObjectAnimator.ofMultiInt(this, "setCoordinates", path);
|
||||||
|
break;
|
||||||
|
case R.id.multi_float:
|
||||||
|
// Use a multi-float setter to animate along a Path. The method
|
||||||
|
// changeCoordinates(float x, float y) is called on this during the animation.
|
||||||
|
mAnimator = ObjectAnimator.ofMultiFloat(this, "changeCoordinates", path);
|
||||||
|
break;
|
||||||
|
case R.id.named_setter:
|
||||||
|
// Use the named "point" property to animate along the Path.
|
||||||
|
// There must be a method setPoint(PointF) on the animated object.
|
||||||
|
// Because setPoint takes a PointF parameter, no TypeConverter is necessary.
|
||||||
|
// In this case, the animated object is PathAnimations.
|
||||||
|
mAnimator = ObjectAnimator.ofObject(this, "point", null, path);
|
||||||
|
break;
|
||||||
|
case R.id.property_setter:
|
||||||
|
// Use the POINT_PROPERTY property to animate along the Path.
|
||||||
|
// POINT_PROPERTY takes a Point, not a PointF, so the TypeConverter
|
||||||
|
// PointFToPointConverter is necessary.
|
||||||
|
mAnimator = ObjectAnimator.ofObject(this, POINT_PROPERTY,
|
||||||
|
new PointFToPointConverter(), path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mAnimator.setDuration(10000);
|
||||||
|
mAnimator.setRepeatMode(Animation.RESTART);
|
||||||
|
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
|
||||||
|
mAnimator.setInterpolator(new LinearInterpolator());
|
||||||
|
mAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CanvasView extends FrameLayout {
|
||||||
|
|
||||||
|
Path mPath = new Path();
|
||||||
|
|
||||||
|
Paint mPathPaint = new Paint();
|
||||||
|
|
||||||
|
public CanvasView(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CanvasView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CanvasView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
setWillNotDraw(false);
|
||||||
|
mPathPaint.setColor(0xFFFF0000);
|
||||||
|
mPathPaint.setStrokeWidth(2.0f);
|
||||||
|
mPathPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
|
if (changed) {
|
||||||
|
Matrix scale = new Matrix();
|
||||||
|
float scaleWidth = (right-left)/TRAVERSE_PATH_SIZE;
|
||||||
|
float scaleHeight= (bottom-top)/TRAVERSE_PATH_SIZE;
|
||||||
|
scale.setScale(scaleWidth, scaleHeight);
|
||||||
|
sTraversalPath.transform(scale, mPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getPath() {
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
canvas.drawPath(mPath, mPathPaint);
|
||||||
|
super.draw(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PointFToPointConverter extends TypeConverter<PointF, Point> {
|
||||||
|
Point mPoint = new Point();
|
||||||
|
|
||||||
|
public PointFToPointConverter() {
|
||||||
|
super(PointF.class, Point.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Point convert(PointF value) {
|
||||||
|
mPoint.set(Math.round(value.x), Math.round(value.y));
|
||||||
|
return mPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user