Android动画学习(五)之属性动画实现Tween的效果和高级属性示例
来源:互联网 发布:重庆时时彩 遗漏数据 编辑:程序博客网 时间:2024/05/18 02:01
Android动画学习(五)之属性动画实现Tween的效果和高级属性示例
在上篇博客中我们学习了属性动画的使用,主要介绍了概念的知识,这篇通过实现Tween的四种效果和高级属性示例展示加深对属性动画的掌握
属性动画实现Tween的四种效果
属性动画的实现方式有两种方式:XMl和Java代码配置
animator配置
在res下新建animator文件夹,新建AAA.xml文件。在set属性下新建设置动画属性.
alpha.xml
实现透明效果
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="1000" android:propertyName="alpha" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" /></set>
scale.xml
实现缩放效果
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="scaleY" android:valueFrom="3" android:valueTo="1" android:valueType="floatType" /></set>
translate.xml
实现平移效果
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="translationX" android:valueFrom="-400" android:valueTo="1" android:valueType="floatType" /></set>
rotate.xml
实现旋转效果
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:valueType="floatType" /></set>
animatorset.xml
实现组合效果
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="2000" android:propertyName="translationX" android:valueFrom="-500" android:valueTo="0" android:valueType="floatType" > </objectAnimator> <set android:ordering="together" > <objectAnimator android:duration="3000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:valueType="floatType" > </objectAnimator> <set android:ordering="sequentially" > <objectAnimator android:duration="1500" android:propertyName="alpha" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" > </objectAnimator> <objectAnimator android:duration="1500" android:propertyName="alpha" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" > </objectAnimator> </set> </set></set>
Layout布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include layout="@layout/titlebar" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0.5" android:text="XML" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="xml_alph" android:text="alph" android:textAllCaps="false" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="xml_scale" android:text="scale" android:textAllCaps="false" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="xml_translate" android:text="translate" android:textAllCaps="false" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="xml_rotate" android:text="rotate" android:textAllCaps="false" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0.5" android:text="JAVA" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="java_alph" android:text="alph" android:textAllCaps="false" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="java_scale" android:text="scale" android:textAllCaps="false" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="java_translate" android:text="translate" android:textAllCaps="false" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="java_rotate" android:text="rotate" android:textAllCaps="false" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="组合" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="XMLSetAnimator" android:text="XMLSet" android:textAllCaps="false" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="JAVASetAnimator" android:text="JAVAset" android:textAllCaps="false" /> </LinearLayout> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" app:srcCompat="@drawable/mei3" /></LinearLayout>
代码实现:
XML:
public void xml_alph(View view) {//透明度 Animator animator = AnimatorInflater.loadAnimator(AttributeAnimatonActivity.this, R.animator.alpha); animator.setTarget(v); animator.start(); } public void xml_scale(View view) {//缩放 Animator animator = AnimatorInflater.loadAnimator(AttributeAnimatonActivity.this, R.animator.scale); animator.setTarget(v); animator.start(); } public void xml_translate(View view) {//平移 Animator animator = AnimatorInflater.loadAnimator(AttributeAnimatonActivity.this, R.animator.translate); animator.setTarget(v); animator.start(); } public void xml_rotate(View view) {//旋转 Animator animator = AnimatorInflater.loadAnimator(AttributeAnimatonActivity.this, R.animator.rotate); animator.setTarget(v); animator.start(); } public void JAVASetAnimator(View view) {//组合效果 ObjectAnimator moveIn = ObjectAnimator.ofFloat(iv, "translationX", -500f, 0f); ObjectAnimator rotate = ObjectAnimator.ofFloat(iv, "rotation", 0f, 360f); ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(iv, "alpha", 1f, 0f, 1f); animSet = new AnimatorSet(); animSet.play(rotate).with(fadeInOut).after(moveIn); animSet.setDuration(5000); animSet.start(); } public void XMLSetAnimator(View view) {//将图片先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作 Animator animator = AnimatorInflater.loadAnimator(AttributeAnimatonActivity.this, R.animator.animatorset); animator.setTarget(v); animator.start(); }
Xml效果:
Java实现:
/* View从透明到完全不透明,时间1s,先加速再减速: */ public void java_alph(View view) {//透明效果 ObjectAnimator animator = ObjectAnimator.ofFloat(iv, "alpha", 0f, 1f); animator.setDuration(1000); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.start(); } /*x轴从自身50%缩放到自身200%,y轴从自身50%缩放到自身200%,中心点(10%,10%)时间1s,先加速再减速: */ public void java_scale(View view) {//缩放效果 PropertyValuesHolder valuesHolderX = PropertyValuesHolder.ofFloat("scaleX", 0.5f, 1f); PropertyValuesHolder valuesHolderY = PropertyValuesHolder.ofFloat("scaleY", 0.5f, 2f); //两个中心点其实可以用set方法直接设置,iv.setPivotX(pivotX) float pivotX = iv.getWidth() * 0.1f; float pivotY = iv.getHeight() * 0.1f; PropertyValuesHolder valuesHolderPvX = PropertyValuesHolder.ofFloat("pivotX", pivotX, pivotX); PropertyValuesHolder valuesHolderPvY = PropertyValuesHolder.ofFloat("pivotY", pivotY, pivotY);// ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(iv, valuesHolderX, valuesHolderY, valuesHolderPvX, valuesHolderPvY); ObjectAnimator animator = ObjectAnimator.ofFloat(iv, "scaleY", 1f, 3f, 1f);//在垂直方向上放大3倍再还原 animator.setDuration(1000); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.start(); } /*x轴从自身位置50%向右平移相对于自己宽度100%的距离,y轴从自身位置50%向下平移相对于自己100%高度的距离,时间1s,先加速再减速: */ public void java_translate(View view) {//平移效果 PropertyValuesHolder valuesHolderX = PropertyValuesHolder.ofFloat("translationX", iv.getWidth() * 0.5f, iv.getWidth() * 1.5f); PropertyValuesHolder valuesHolderY = PropertyValuesHolder.ofFloat("translationY", iv.getHeight() * 0.5f, iv.getHeight() * 1.5f);// ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(iv, valuesHolderX, valuesHolderY); float curTranslationX = iv.getTranslationX();//TextView先向左移出屏幕,然后再移动回来 ObjectAnimator animator = ObjectAnimator.ofFloat(iv, "translationX", curTranslationX, -500f, curTranslationX); animator.setDuration(1000); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.start(); } /*View绕自身中心点(10%,10%)位置,从-270旋转到180,时间1s,先加速再减速 : */ public void java_rotate(View view) {//旋转效果 PropertyValuesHolder valuesHolderX = PropertyValuesHolder.ofFloat("rotation", -270f, 180f); //两个中心点其实可以用set方法直接设置,iv.setPivotX(pivotX) float pivotX = iv.getWidth() * 0.1f; float pivotY = iv.getHeight() * 0.1f; PropertyValuesHolder valuesHolderPvX = PropertyValuesHolder.ofFloat("pivotX", pivotX, pivotX); PropertyValuesHolder valuesHolderPvY = PropertyValuesHolder.ofFloat("pivotY", pivotY, pivotY);// ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(iv, valuesHolderX, valuesHolderPvX, valuesHolderPvY); ObjectAnimator animator = ObjectAnimator.ofFloat(iv, "rotation", 0f, 360f);//一次360度的旋转 animator.setDuration(1000); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.start(); }
Java效果:
高级属性之自定义TypeEvaluator
自定义TypeEvaluator
public class PointEvaluator implements TypeEvaluator { @Override public Object evaluate(float fraction, Object startValue, Object endValue) { Point startPoint = (Point) startValue; Point endPoint = (Point) endValue; float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX()); float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY()); Point point = new Point(x, y); return point; }}
引用布局
<com.example.administrator.androidanimation.View.TypeEvaluatorView android:layout_width="match_parent" android:layout_height="match_parent" />
Activity调用
public class TypeEvaluatorActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_type_evaluator); Point point1 = new Point(0, 0); Point point2 = new Point(300, 300); ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), point1, point2); anim.setDuration(5000); anim.start(); }}
实现效果:
注:代码参考郭霖大神的属性动画讲解,如有侵权,请及时联系
高级属性之自定义TimeInterpolator
自定义TimeInterpolator
/** * 自定义插值器 */ public class MyDecelerateAccelerateInterpolator implements TimeInterpolator { @Override public float getInterpolation(float input) { if (input <= 0.5) { return (float) (Math.sin(Math.PI * input)) / 2; } else { return (float) (2 - Math.sin(Math.PI * input)) / 2; } } }
引用布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administrator.androidanimation.activity.TypeEvaluatorActivity"> <include layout="@layout/titlebar" android:id="@+id/include" /> <ImageView android:id="@+id/imageView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_alignParentTop="true" app:srcCompat="@drawable/m3" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="start" android:text="开始动画" android:layout_below="@+id/include" android:layout_alignParentStart="true" /> <Button android:id="@+id/button16" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/button" android:layout_alignParentEnd="true" android:onClick="cancle" android:text="结束动画" /></RelativeLayout>
Activity调用
public class TimeInterpolatorActivity extends AppCompatActivity { private ImageView iv; private ObjectAnimator objectAnimator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_time_interpolaator); TextView textView = (TextView) findViewById(R.id.tv_title); //设置标题 textView.setText("自定义Interpolator"); iv = (ImageView) findViewById(R.id.imageView2); } public void start(View view) { float curTranslationY = iv.getTranslationY();//获取到当前控件的translationX的位置 objectAnimator = ObjectAnimator.ofFloat(iv, "translationY", curTranslationY, -500f, curTranslationY); objectAnimator.setDuration(3000); objectAnimator.setRepeatCount(1); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); objectAnimator.addPauseListener(new Animator.AnimatorPauseListener() { @Override public void onAnimationPause(Animator animation) {//通知动画暂停。 } @Override public void onAnimationResume(Animator animation) {//通知动画得到恢复,之前被暂停后。 } }); objectAnimator.start(); } public void cancle(View view) { objectAnimator.cancel(); }
实现效果:
高级属性之自定义Path路径动画
自定义View设置路径Path
/** *自定义View设置Path */public class PathView extends View { /** * Logging tag. */ public static final String LOG_TAG = "PathView"; /** * The paint for the path. */ private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); /** * Utils to catch the paths from the svg. */ private final SvgUtils svgUtils = new SvgUtils(paint); /** * All the paths provided to the view. Both from Path and Svg. */ private List<SvgUtils.SvgPath> paths = new ArrayList<SvgUtils.SvgPath>(0); /** * This is a lock before the view is redrawn * or resided it must be synchronized with this object. */ private final Object mSvgLock = new Object(); /** * Thread for working with the object above. */ private Thread mLoader; /** * The svg image from the raw directory. */ private int svgResourceId; /** * Object that build the animation for the path. */ private AnimatorBuilder animatorBuilder; /** * The progress of the drawing. */ private float progress = 0f; /** * If the used colors are from the svg or from the set color. */ private boolean naturalColors; /** * If the view is filled with its natural colors after path drawing. */ private boolean fillAfter; /** * The width of the view. */ private int width; /** * The height of the view. */ private int height; /** * Default constructor. * * @param context The Context of the application. */ public PathView(Context context) { this(context, null); } /** * Default constructor. * * @param context The Context of the application. * @param attrs attributes provided from the resources. */ public PathView(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * Default constructor. * * @param context The Context of the application. * @param attrs attributes provided from the resources. * @param defStyle Default style. */ public PathView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); paint.setStyle(Paint.Style.STROKE); getFromAttributes(context, attrs); } /** * Get all the fields from the attributes . * * @param context The Context of the application. * @param attrs attributes provided from the resources. */ private void getFromAttributes(Context context, AttributeSet attrs) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PathView); try { if (a != null) { paint.setColor(a.getColor(R.styleable.PathView_pathColor, 0xff0000cc)); paint.setStrokeWidth(a.getFloat(R.styleable.PathView_pathWidth, 8.0f)); svgResourceId = a.getResourceId(R.styleable.PathView_svg, 0); } } finally { if (a != null) { a.recycle(); } } } /** * Set paths to be drawn and animated. * * @param paths - Paths that can be drawn. */ public void setPaths(final List<Path> paths) { for (Path path : paths) { this.paths.add(new SvgUtils.SvgPath(path, paint)); } synchronized (mSvgLock) { updatePathsPhaseLocked(); } } /** * Set path to be drawn and animated. * * @param path - Paths that can be drawn. */ public void setPath(final Path path) { paths.add(new SvgUtils.SvgPath(path, paint)); synchronized (mSvgLock) { updatePathsPhaseLocked(); } } /** * Animate this property. It is the percentage of the path that is drawn. * It must be [0,1]. * * @param percentage float the percentage of the path. */ public void setPercentage(float percentage) { if (percentage < 0.0f || percentage > 1.0f) { throw new IllegalArgumentException("setPercentage not between 0.0f and 1.0f"); } progress = percentage; synchronized (mSvgLock) { updatePathsPhaseLocked(); } invalidate(); } /** * This refreshes the paths before draw and resize. */ private void updatePathsPhaseLocked() { final int count = paths.size(); for (int i = 0; i < count; i++) { SvgUtils.SvgPath svgPath = paths.get(i); svgPath.path.reset(); svgPath.measure.getSegment(0.0f, svgPath.length * progress, svgPath.path, true); // Required only for Android 4.4 and earlier svgPath.path.rLineTo(0.0f, 0.0f); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); synchronized (mSvgLock) { canvas.save(); canvas.translate(getPaddingLeft(), getPaddingTop()); final int count = paths.size(); for (int i = 0; i < count; i++) { final SvgUtils.SvgPath svgPath = paths.get(i); final Path path = svgPath.path; final Paint paint1 = naturalColors ? svgPath.paint : paint; canvas.drawPath(path, paint1); }// fillAfter(canvas); canvas.restore(); } } /** * If there is svg , the user called setFillAfter(true) and the progress is finished. * * @param canvas Draw to this canvas. */ private void fillAfter(final Canvas canvas) { if (svgResourceId != 0 && fillAfter && progress == 1f) { svgUtils.drawSvgAfter(canvas, width, height); } } @Override protected void onSizeChanged(final int w, final int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (mLoader != null) { try { mLoader.join(); } catch (InterruptedException e) { Log.e(LOG_TAG, "Unexpected error", e); } } if (svgResourceId != 0) { mLoader = new Thread(new Runnable() { @Override public void run() { svgUtils.load(getContext(), svgResourceId); synchronized (mSvgLock) { width = w - getPaddingLeft() - getPaddingRight(); height = h - getPaddingTop() - getPaddingBottom(); paths = svgUtils.getPathsForViewport(width, height); updatePathsPhaseLocked(); } } }, "SVG Loader"); mLoader.start(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (svgResourceId != 0) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(widthSize, heightSize); return; } int desiredWidth = 0; int desiredHeight = 0; final float strokeWidth = paint.getStrokeWidth() / 2; for (SvgUtils.SvgPath path : paths) { desiredWidth += path.bounds.left + path.bounds.width() + strokeWidth; desiredHeight += path.bounds.top + path.bounds.height() + strokeWidth; } int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(widthMeasureSpec); int measuredWidth, measuredHeight; if (widthMode == MeasureSpec.AT_MOST) { measuredWidth = desiredWidth; } else { measuredWidth = widthSize; } if (heightMode == MeasureSpec.AT_MOST) { measuredHeight = desiredHeight; } else { measuredHeight = heightSize; } setMeasuredDimension(measuredWidth, measuredHeight); } /** * If the real svg need to be drawn after the path animation. * * @param fillAfter - boolean if the view needs to be filled after path animation. */ public void setFillAfter(final boolean fillAfter) { this.fillAfter = fillAfter; } /** * If you want to use the colors from the svg. */ public void useNaturalColors() { naturalColors = true; } /** * Animator for the paths of the view. * * @return The AnimatorBuilder to build the animation. */ public AnimatorBuilder getPathAnimator() { if (animatorBuilder == null) { animatorBuilder = new AnimatorBuilder(this); } return animatorBuilder; } /** * Get the path color. * * @return The color of the paint. */ public int getPathColor() { return paint.getColor(); } /** * Set the path color. * * @param color -The color to set to the paint. */ public void setPathColor(final int color) { paint.setColor(color); } /** * Get the path width. * * @return The width of the paint. */ public float getPathWidth() { return paint.getStrokeWidth(); } /** * Set the path width. * * @param width - The width of the path. */ public void setPathWidth(final float width) { paint.setStrokeWidth(width); } /** * Get the svg resource id. * * @return The svg raw resource id. */ public int getSvgResource() { return svgResourceId; } /** * Set the svg resource id. * * @param svgResource - The resource id of the raw svg. */ public void setSvgResource(int svgResource) { svgResourceId = svgResource; } /** * Object for building the animation of the path of this view. */ public static class AnimatorBuilder { /** * Duration of the animation. */ private int duration = 350; /** * Interpolator for the time of the animation. */ private Interpolator interpolator; /** * The delay before the animation. */ private int delay = 0; /** * ObjectAnimator that constructs the animation. */ private final ObjectAnimator anim; /** * Listener called before the animation. */ private ListenerStart listenerStart; /** * Listener after the animation. */ private ListenerEnd animationEnd; /** * Animation listener. */ private PathViewAnimatorListener pathViewAnimatorListener; /** * Default constructor. * * @param pathView The view that must be animated. */ public AnimatorBuilder(final PathView pathView) { anim = ObjectAnimator.ofFloat(pathView, "percentage", 0.0f, 1.0f); } /** * Set the duration of the animation. * * @param duration - The duration of the animation. * @return AnimatorBuilder. */ public AnimatorBuilder duration(final int duration) { this.duration = duration; return this; } /** * Set the Interpolator. * * @param interpolator - Interpolator. * @return AnimatorBuilder. */ public AnimatorBuilder interpolator(final Interpolator interpolator) { this.interpolator = interpolator; return this; } /** * The delay before the animation. * * @param delay - int the delay * @return AnimatorBuilder. */ public AnimatorBuilder delay(final int delay) { this.delay = delay; return this; } /** * Set a listener before the start of the animation. * * @param listenerStart an interface called before the animation * @return AnimatorBuilder. */ public AnimatorBuilder listenerStart(final ListenerStart listenerStart) { this.listenerStart = listenerStart; if (pathViewAnimatorListener == null) { pathViewAnimatorListener = new PathViewAnimatorListener(); anim.addListener(pathViewAnimatorListener); } return this; } /** * Set a listener after of the animation. * * @param animationEnd an interface called after the animation * @return AnimatorBuilder. */ public AnimatorBuilder listenerEnd(final ListenerEnd animationEnd) { this.animationEnd = animationEnd; if (pathViewAnimatorListener == null) { pathViewAnimatorListener = new PathViewAnimatorListener(); anim.addListener(pathViewAnimatorListener); } return this; } /** * Starts the animation. */ public void start() { anim.setDuration(duration); anim.setInterpolator(interpolator); anim.setStartDelay(delay); anim.start(); } /** * Animation listener to be able to provide callbacks for the caller. */ private class PathViewAnimatorListener implements Animator.AnimatorListener { @Override public void onAnimationStart(Animator animation) { if (listenerStart != null) listenerStart.onAnimationStart(); } @Override public void onAnimationEnd(Animator animation) { if (animationEnd != null) animationEnd.onAnimationEnd(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } } /** * Called when the animation start. */ public interface ListenerStart { /** * Called when the path animation start. */ void onAnimationStart(); } /** * Called when the animation end. */ public interface ListenerEnd { /** * Called when the path animation end. */ void onAnimationEnd(); } }}
引用布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f0f0f0" tools:context=".activity.MainActivity"> <com.example.administrator.androidanimation.View.PathView android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" /> <ImageView android:id="@+id/iv" android:layout_width="100px" android:layout_height="100px" android:layout_marginLeft="100px" android:layout_marginTop="100px" app:srcCompat="@drawable/clear" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:onClick="startAnim" android:text="太阳运动" android:textSize="18sp" /></RelativeLayout>
Activity调用
public class PathAnimActivity extends AppCompatActivity { private ImageView iv; private int screenWidth; private int screenHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_path_anim); iv = (ImageView) findViewById(R.id.iv); screenWidth = getResources().getDisplayMetrics().widthPixels; screenHeight = getResources().getDisplayMetrics().heightPixels; } public void startAnim(View view) { Path path = new Path(); path.moveTo(100, 100); path.quadTo(screenWidth - 300, 200, screenWidth - 100, screenHeight - 600); ObjectAnimator animator = ObjectAnimator.ofFloat(iv, View.X, View.Y, path); animator.setDuration(2000); animator.setRepeatCount(1); animator.setRepeatMode(ValueAnimator.REVERSE); animator.start(); }
实现效果:
总结
通过对实例的学习,相信对属性动画有了深度的了解。
写博客是为了帮助开发者学习使用技术,同时巩固自己所学技术。如果此篇博客有助于您的学习,那是我的荣幸!如果此篇博客有任何瑕疵,请多多指教!在此感谢您的学习和指教!
阅读全文
0 0
- Android动画学习(五)之属性动画实现Tween的效果和高级属性示例
- android学习笔记(九)——动画效果的实现1tween动画
- Android中的tween动画, 帧动画, 和3.0以后的属性动画的用法及不同!
- Android动画详解之Android 动画属性和实现方法之属性动画(三)
- android属性动画效果的实现之ObjectAnimator
- Android动画效果Animation之Tween实现简单动画
- Android动画Animation之Tween用代码实现动画效果
- Android动画效果Animation之Tween实现简单动画
- android Tween Animations(动画效果-代码实现)的使用
- Tween动画属性介绍
- Android动画效果之Tween Animation(补间动画)
- Android动画效果之Tween Animation(补间动画)
- Android动画详解之Android 动画属性和实现方法之帧动画(二)
- Android动画效果之初识Property Animation(属性动画)
- Android动画效果之初识Property Animation(属性动画)
- Android动画效果之Property Animation进阶(属性动画)
- Android动画效果之- Property Animation(属性动画)
- Android动画效果之初识Property Animation(属性动画)
- chrome 插件开发入门
- 使用jedis操作redis常用方法
- 划分树
- POJ 3037 Skiing (搜索 或 spfa)
- android性能优化之布局优化
- Android动画学习(五)之属性动画实现Tween的效果和高级属性示例
- c#微信服务器配置
- Codeforces Round #286 (Div. 2) A. Mr. Kitayuta's Gift
- 可变参数与自动拆箱和自动装箱
- 计算几何小结:叉积
- 实验:minikuber上运行简单程序
- Woocommerce Product Filter插件——为不同类别设置不同filter
- 生活中的单例——只爱一个人
- Tomcat单机多实例部署实战