看这篇文章之前先看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