QuxianActivity.java 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package com.xunao.effectdemo.activity;
  2. import android.animation.Animator;
  3. import android.animation.ValueAnimator;
  4. import android.app.Activity;
  5. import android.graphics.Path;
  6. import android.graphics.PathMeasure;
  7. import android.os.Bundle;
  8. import android.util.Log;
  9. import android.view.View;
  10. import android.view.animation.Animation;
  11. import android.view.animation.AnimationSet;
  12. import android.view.animation.LinearInterpolator;
  13. import android.view.animation.RotateAnimation;
  14. import android.view.animation.TranslateAnimation;
  15. import android.widget.Button;
  16. import android.widget.RelativeLayout;
  17. import androidx.annotation.Nullable;
  18. import com.xunao.effectdemo.R;
  19. /**
  20. * author : 程中强
  21. * e-mail : 740479946@qq.com
  22. * date : 2022/8/1016:44
  23. * desc :
  24. * version: 1.0
  25. */
  26. public class QuxianActivity extends Activity {
  27. private View view,view2;
  28. private RelativeLayout rl;
  29. private Button btn;
  30. private float[] mCurrentPosition = new float[2];
  31. @Override
  32. protected void onCreate(@Nullable Bundle savedInstanceState) {
  33. super.onCreate(savedInstanceState);
  34. setContentView(R.layout.activity_quxian);
  35. init();
  36. }
  37. void init(){
  38. view = findViewById(R.id.view);
  39. view2= findViewById(R.id.view2);
  40. rl = findViewById(R.id.rl);
  41. AnimationSet aset_4=new AnimationSet(true);
  42. TranslateAnimation aa_4=new TranslateAnimation(Animation.RELATIVE_TO_PARENT,0,Animation.RELATIVE_TO_PARENT, -0.5f,
  43. Animation.RELATIVE_TO_PARENT, 0,Animation.RELATIVE_TO_PARENT, 0.5f);
  44. aa_4.setDuration(2000);
  45. aset_4.addAnimation(aa_4);
  46. aset_4.setFillAfter(false);
  47. // view.startAnimation(aset_4);
  48. view.setOnClickListener(v->{
  49. bse();
  50. });
  51. btn =findViewById(R.id.btn);
  52. btn.setOnClickListener(v->{
  53. bse();
  54. });
  55. // new Thread(new Runnable() {
  56. // @Override
  57. // public void run() {
  58. // try {
  59. // Thread.sleep(300);
  60. // bse();
  61. // } catch (InterruptedException e) {
  62. // e.printStackTrace();
  63. // }
  64. // }
  65. // }).start();
  66. bse();
  67. }
  68. void bse(){
  69. AnimationSet aset_2=new AnimationSet(true);
  70. RotateAnimation aa_2=new RotateAnimation(0,360,
  71. Animation.RELATIVE_TO_SELF,0.5f,
  72. Animation.RELATIVE_TO_SELF,0.5f);
  73. aa_2.setDuration(2000);
  74. aset_2.setRepeatCount(-1);
  75. aset_2.addAnimation(aa_2);
  76. int startA[] = new int[2];
  77. view.getLocationInWindow(startA);
  78. Log.e("MyTag","startA:"+startA[0]+" "+startA[1]);
  79. int endB[] = new int[2];
  80. view2.getLocationInWindow(endB);
  81. Log.e("MyTag","endB:"+endB[0]);
  82. int parentC[] = new int[2];
  83. rl.getLocationInWindow(parentC);
  84. Log.e("MyTag","parentC:"+rl.getHeight()+" "+ (float)rl.getWidth());
  85. float startX = 200;
  86. float startY = -100 ;
  87. //商品终点坐标:购物车起始点-父布局起始点
  88. float toX = 10;
  89. float toY = 350 ;
  90. // 四、计算中间动画的插值坐标(贝塞尔曲线)(其实就是用贝塞尔曲线来完成起终点的过程)
  91. //开始绘制贝塞尔曲线
  92. Path path = new Path();
  93. //移动到起始点(贝塞尔曲线的起点)
  94. path.moveTo(500, -200);
  95. //使用二次萨贝尔曲线:注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大,一般按照下面的式子取即可
  96. path.quadTo(350, 150, -50, 200);
  97. //mPathMeasure用来计算贝塞尔曲线的曲线长度和贝塞尔曲线中间插值的坐标,
  98. // 如果是true,path会形成一个闭环
  99. final PathMeasure mPathMeasure = new PathMeasure(path, false);
  100. //★★★属性动画实现(从0到贝塞尔曲线的长度之间进行插值计算,获取中间过程的距离值)
  101. ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());
  102. valueAnimator.setDuration(1200);
  103. // 匀速线性插值器
  104. valueAnimator.setInterpolator(new LinearInterpolator());
  105. valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  106. @Override
  107. public void onAnimationUpdate(ValueAnimator animation) {
  108. // 这里这个值是中间过程中的曲线长度(下面根据这个值来得出中间点的坐标值)
  109. float value = (Float) animation.getAnimatedValue();
  110. // ★★★★★获取当前点坐标封装到mCurrentPosition
  111. // 离的坐标点和切线,pos会自动填充上坐标,这个方法很重要。
  112. mPathMeasure.getPosTan(value, mCurrentPosition, null);//mCurrentPosition此时就是中间距离点的坐标值
  113. Log.e("MyTag","获取坐标:"+mCurrentPosition[0]);
  114. view2.setTranslationX(mCurrentPosition[0]);
  115. view2.setTranslationY(mCurrentPosition[1]);
  116. // 此处为设置旋转的代码
  117. // view2.setRotation((float) ((500-mCurrentPosition[1])/580)*360);
  118. }
  119. });
  120. //五、 开始执行动画
  121. valueAnimator.setObjectValues(aa_2);
  122. valueAnimator.start();
  123. // view2.startAnimation(aset_2);
  124. //六、动画结束后的处理
  125. valueAnimator.addListener(new Animator.AnimatorListener() {
  126. @Override
  127. public void onAnimationStart(Animator animation) {
  128. }
  129. //当动画结束后:
  130. @Override
  131. public void onAnimationEnd(Animator animation) {
  132. view2.clearAnimation();
  133. // 购物车的数量加1
  134. // count++;
  135. // tvGoodNum.setText(count+"");
  136. // // 把移动的图片imageview从父布局里移除
  137. // rl.removeView(imageView);
  138. // // 开始一个放大动画
  139. // Animation scaleAnim = AnimationUtils.loadAnimation(FoodActivity2.this, R.anim.shop_scale);
  140. // ivGoodsCar.startAnimation(scaleAnim);
  141. }
  142. @Override
  143. public void onAnimationCancel(Animator animation) {
  144. }
  145. @Override
  146. public void onAnimationRepeat(Animator animation) {
  147. }
  148. });
  149. }
  150. }