package com.xunao.effectdemo.activity; import android.animation.Animator; import android.animation.ValueAnimator; import android.app.Activity; import android.graphics.Path; import android.graphics.PathMeasure; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.RelativeLayout; import androidx.annotation.Nullable; import com.xunao.effectdemo.R; /** * author : 程中强 * e-mail : 740479946@qq.com * date : 2022/8/1016:44 * desc : * version: 1.0 */ public class QuxianActivity extends Activity { private View view,view2; private RelativeLayout rl; private Button btn; private float[] mCurrentPosition = new float[2]; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_quxian); init(); } void init(){ view = findViewById(R.id.view); view2= findViewById(R.id.view2); rl = findViewById(R.id.rl); AnimationSet aset_4=new AnimationSet(true); TranslateAnimation aa_4=new TranslateAnimation(Animation.RELATIVE_TO_PARENT,0,Animation.RELATIVE_TO_PARENT, -0.5f, Animation.RELATIVE_TO_PARENT, 0,Animation.RELATIVE_TO_PARENT, 0.5f); aa_4.setDuration(2000); aset_4.addAnimation(aa_4); aset_4.setFillAfter(false); // view.startAnimation(aset_4); view.setOnClickListener(v->{ bse(); }); btn =findViewById(R.id.btn); btn.setOnClickListener(v->{ bse(); }); // new Thread(new Runnable() { // @Override // public void run() { // try { // Thread.sleep(300); // bse(); // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // }).start(); bse(); } void bse(){ AnimationSet aset_2=new AnimationSet(true); RotateAnimation aa_2=new RotateAnimation(0,360, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF,0.5f); aa_2.setDuration(2000); aset_2.setRepeatCount(-1); aset_2.addAnimation(aa_2); int startA[] = new int[2]; view.getLocationInWindow(startA); Log.e("MyTag","startA:"+startA[0]+" "+startA[1]); int endB[] = new int[2]; view2.getLocationInWindow(endB); Log.e("MyTag","endB:"+endB[0]); int parentC[] = new int[2]; rl.getLocationInWindow(parentC); Log.e("MyTag","parentC:"+rl.getHeight()+" "+ (float)rl.getWidth()); float startX = 200; float startY = -100 ; //商品终点坐标:购物车起始点-父布局起始点 float toX = 10; float toY = 350 ; // 四、计算中间动画的插值坐标(贝塞尔曲线)(其实就是用贝塞尔曲线来完成起终点的过程) //开始绘制贝塞尔曲线 Path path = new Path(); //移动到起始点(贝塞尔曲线的起点) path.moveTo(500, -200); //使用二次萨贝尔曲线:注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大,一般按照下面的式子取即可 path.quadTo(350, 150, -50, 200); //mPathMeasure用来计算贝塞尔曲线的曲线长度和贝塞尔曲线中间插值的坐标, // 如果是true,path会形成一个闭环 final PathMeasure mPathMeasure = new PathMeasure(path, false); //★★★属性动画实现(从0到贝塞尔曲线的长度之间进行插值计算,获取中间过程的距离值) ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength()); valueAnimator.setDuration(1200); // 匀速线性插值器 valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // 这里这个值是中间过程中的曲线长度(下面根据这个值来得出中间点的坐标值) float value = (Float) animation.getAnimatedValue(); // ★★★★★获取当前点坐标封装到mCurrentPosition // 离的坐标点和切线,pos会自动填充上坐标,这个方法很重要。 mPathMeasure.getPosTan(value, mCurrentPosition, null);//mCurrentPosition此时就是中间距离点的坐标值 Log.e("MyTag","获取坐标:"+mCurrentPosition[0]); view2.setTranslationX(mCurrentPosition[0]); view2.setTranslationY(mCurrentPosition[1]); // 此处为设置旋转的代码 // view2.setRotation((float) ((500-mCurrentPosition[1])/580)*360); } }); //五、 开始执行动画 valueAnimator.setObjectValues(aa_2); valueAnimator.start(); // view2.startAnimation(aset_2); //六、动画结束后的处理 valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } //当动画结束后: @Override public void onAnimationEnd(Animator animation) { view2.clearAnimation(); // 购物车的数量加1 // count++; // tvGoodNum.setText(count+""); // // 把移动的图片imageview从父布局里移除 // rl.removeView(imageView); // // 开始一个放大动画 // Animation scaleAnim = AnimationUtils.loadAnimation(FoodActivity2.this, R.anim.shop_scale); // ivGoodsCar.startAnimation(scaleAnim); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); } }