Android中属性动画6----ValueAnimator.ofObject的使用(从一个点运动到另一个点(直线))

看这篇文章之前先看https://blog.csdn.net/zhaihaohao1/article/details/80941009
开始讲:

效果图:
这里写图片描述
实现思路如下
1先创建一个估值器:

package com.zhh.myapplication.test1;

import android.animation.TypeEvaluator;
import android.graphics.Point;

import com.orhanobut.logger.Logger;

/**
 * Created by 16838 on 2018/7/5.
 * 就是告诉动画系统如何从初始值过度到结束值
 * 产生动画平滑滑动的值
 * 从开始到结束的所有坐标值
 * 保存在Point
 *
 *  估值器
 */
public class MyTypeEvaluator implements TypeEvaluator {
    /**
     * fraction动画的完成度
     * startValue动画的初始值
     * endValue动画的结束值
     * @param fraction
     * @param startValue
     * @param endValue
     * @return
     */
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        Point startPoint = (Point) startValue;
        Point endPoint = (Point) endValue;
//      直线公式
        float mX = startPoint.x + fraction * (endPoint.x - startPoint.x);
        float mY = startPoint.y + fraction * (endPoint.y - startPoint.y);
        Point point = new Point((int)mX, (int)mY);
//      这里会产生从开始画滑动到结束的所有坐标
        return point;
    }

}

2自定义控件结合动画绘制

package com.zhh.myapplication.test1;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.LinearInterpolator;

import com.orhanobut.logger.Logger;

/**
 * Created by 16838 on 2018/7/5.
 */
public class MyAnimView extends View {
//  设置圆的半径
    public static final float RADIUS = 100f;
//  设置画笔
    private Paint mPaint;

    /**
     * 构造方法,在类里面new对象
     * @param context
     */
    public MyAnimView(Context context) {
        super(context);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }

    /**
     * 测量,设置宽高
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//      设置本控件的宽高
        setMeasuredDimension((int)RADIUS*2, (int)RADIUS*2);

    }

    /**
     * 绘制
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
//      在 onAnimationUpdate 中设置的坐标是屏幕坐标系中的原点
//      在 canvas.drawCircle 是本控件的坐标系中的坐标点
//      设置时宽高的一半,刚好是在中间
        canvas.drawCircle(getMeasuredWidth()/2, getMeasuredHeight()/2,RADIUS,mPaint);
    }

    /**
     * 动画
     * 根据坐标点,绘制
     * @param startPoint
     * @param endPoint
     */
    public void startAnimation(Point startPoint,Point endPoint) {
        ValueAnimator anim = ValueAnimator.ofObject(new MyTypeEvaluator(), startPoint, endPoint);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Point currentPoint = (Point) animation.getAnimatedValue();
//              设置相对于屏幕的原点
                MyAnimView.this.setX(currentPoint.x);
                MyAnimView.this.setY(currentPoint.y);
//              绘制
                invalidate();
            }
        });
        anim.setDuration(1000);
//      动画完成后的监听
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                ViewGroup viewGroup = (ViewGroup) getParent();
                Logger.t("111").d("viewGroup"+viewGroup.getChildCount());
                viewGroup.removeView(MyAnimView.this);
            }
        });
//      插值器,设置变化方式,这里是匀速,运动
        anim.setInterpolator(new LinearInterpolator());
        anim.start();
    }

}

3在activity中,拿到起始坐标,并开始动画

package com.zhh.myapplication.test1;

import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.orhanobut.logger.Logger;
import com.zhh.myapplication.R;

public class Main6Activity extends Activity {
    private Button button1;
    private Button button2;
    private Context context;
//    private MyAnimView myAnimView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main6);
        context=Main6Activity.this;
        button1 = findViewById(R.id.button1);
        button2 = findViewById(R.id.button2);
//        myAnimView = findViewById(R.id.myAnimView);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                button1.getLocationInWindow(locationStart);
//                获取本控件在整个窗口内的绝对坐标
//                也就是绝对坐标系中的坐标
                int[] location = new int[2];
                button1.getLocationInWindow(location);
//              拿到X坐标
                int x = location[0];
//              拿到y坐标
                int y = location[1];
//              把坐标放到Point中
//              Point仅仅放一下坐标
                Point pointStart = new Point(x,y);

//              拿到终点控件的绝对坐标
                int [] locationEnd = new int[2];
                button2.getLocationInWindow(locationEnd);
                int xEnd = locationEnd[0];
                int yEnd = locationEnd[1];
                Point pointEnd = new Point(xEnd,yEnd);
//              实例化对象
                MyAnimView myAnimView=new MyAnimView(context);
//              开始动画传入起点坐标和终点坐标
                myAnimView.startAnimation(pointStart, pointEnd);

                ViewGroup rootView = (ViewGroup) Main6Activity.this.getWindow().getDecorView();
                rootView.addView(myAnimView);



            }
        });
    }


}

4activity_main6中布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhh.myapplication.test1.Main6Activity"
    android:orientation="vertical"
    >
    <Button
        android:id="@+id/button1"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="起点"
        android:layout_marginLeft="250dp"
        />
    <Button
        android:id="@+id/button2"
        android:layout_marginTop="300dp"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="终点"
        android:layout_marginLeft="100dp"
        />




</LinearLayout>

参考
https://blog.csdn.net/guolin_blog/article/details/43536355
https://blog.csdn.net/sinyu890807/article/details/43816093
https://blog.csdn.net/guolin_blog/article/details/44171115

源码下载
TestLayout—–动画
https://download.csdn.net/download/zhaihaohao1/10525191

猜你喜欢

转载自blog.csdn.net/zhaihaohao1/article/details/80941482
今日推荐