轉載請註明出處:http://blog.csdn.net/linglongxin24/article/details/53470872
本文出自【DylanAndroid的博客】
【Android自定義View實戰】之仿百度加載動畫,一種優雅的Loading方式
無意中看到了百度的加載動畫,看起來非常優雅,打算親手造一個。
仿百度加載動畫的重要思路:當第一遍執行完畢後就讓第一個停下來在中間位置,換原來中間位置的第三個開始執行動畫,
以此類推,當第二遍執行完畢後第二個停下來,中間位置的開始執行動畫。
第一個:仿百度加載動畫,用ObjectAnimator屬性動畫操作ImageView的屬性方法實現:
- 1.佈局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="500px"
android:layout_height="500px"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_blue"
android:layout_width="wrap_content"
android:scaleType="matrix"
android:layout_height="wrap_content"
android:src="@mipmap/dot_blue"
android:layout_gravity="center" />
<ImageView
android:id="@+id/iv_yellow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="@mipmap/dot_yellow"
android:layout_gravity="center" />
<ImageView
android:id="@+id/iv_red"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="@mipmap/dot_red"
android:layout_gravity="center" />
</FrameLayout>
- 2.代碼
package cn.bluemobi.dylan.baiduprogressbar;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
/**
* 仿百度優雅的加載動畫
* Created by dylan on 2016-12-04.
*/
public class BaiduProgressBar extends FrameLayout {
/**
* 開始執行的第一個動畫的索引,
* 由於第一個和第二個同時當執行,
* 當第一遍執行完畢後就讓第一個停下來在中間位置,換原來中間位置的第三個開始執行動畫,
* 以此類推,當第二遍執行完畢後第二個停下來,中間位置的開始執行動畫。
*/
private int startIndex = 0;
/**
* 交換執行動畫的源圖片數組
*/
private int[] src = new int[]{R.mipmap.dot_yellow, R.mipmap.dot_red, R.mipmap.dot_blue};
/**
* 存放三個ImageView的的集合
*/
private List<ImageView> views = new ArrayList<>();
/**
* 讓左邊和右邊動畫同時執行的AnimatorSet對象
*/
private AnimatorSet animatorSet;
/**
* 動畫所執行的最大半徑(即中間點和最左邊的距離)
*/
private int maxRadius = 200;
public BaiduProgressBar(Context context) {
super(context);
init();
}
public BaiduProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BaiduProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* 查找佈局控件
*/
private void assignViews() {
ImageView iv_blue = (ImageView) findViewById(R.id.iv_blue);
ImageView iv_yellow = (ImageView) findViewById(R.id.iv_yellow);
ImageView iv_red = (ImageView) findViewById(R.id.iv_red);
views.add(iv_yellow);
views.add(iv_red);
views.add(iv_blue);
}
/**
* 初始化
*/
private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.baidu_progress_bar, this, true);
assignViews();
startAnimator();
}
/**
* 開始執行動畫
*/
private void startAnimator() {
/**向左來回移動的X位移動畫**/
ObjectAnimator objectAnimatorLeft = ObjectAnimator.ofFloat(views.get(0), "translationX", 0, -maxRadius, 0);
objectAnimatorLeft.setRepeatCount(-1);
objectAnimatorLeft.setDuration(1000);
/**向右來回移動的X位移動畫**/
ObjectAnimator objectAnimatorRight = ObjectAnimator.ofFloat(views.get(1), "translationX", 0, maxRadius, 0);
objectAnimatorRight.setRepeatCount(-1);
objectAnimatorRight.setDuration(1000);
/**動畫組合->讓左右同時執行**/
animatorSet = new AnimatorSet();
animatorSet.play(objectAnimatorRight).with(objectAnimatorLeft);
animatorSet.setInterpolator(new LinearInterpolator());
animatorSet.start();
/**動畫監聽**/
objectAnimatorLeft.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) {
/**每次記錄一下下次應該停止在中間的Image索引,然後和中間的交換**/
if (startIndex == 0) {
sweep(0, 2);
startIndex = 1;
} else {
sweep(1, 2);
startIndex = 0;
}
}
});
}
/**
* 每次讓先執行動畫的目標和中間停止的動畫目標交換
*
* @param a 最先執行的動畫的索引
* @param b 在中間動畫的索引
*/
private void sweep(int a, int b) {
views.get(a).setImageResource(src[b]);
views.get(b).setImageResource(src[a]);
int temp = src[b];
src[b] = src[a];
src[a] = temp;
}
/**
* 在View銷燬時停止動畫
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
animatorSet.cancel();
}
}
第二個:仿百度加載動畫第二種實現方式,用ValueAnimator+原生的ondraw()方法實現:
package cn.bluemobi.dylan.baiduprogressbar;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
/**
* 仿百度優雅的加載動畫
* Created by dylan on 2016-12-04.
*/
public class BaiduProgressBar2 extends View {
/**
* 開始執行的第一個動畫的索引,
* 由於第一個和第二個同時當執行,
* 當第一遍執行完畢後就讓第一個停下來在中間位置,換原來中間位置的第三個開始執行動畫,
* 以此類推,當第二遍執行完畢後第二個停下來,中間位置的開始執行動畫。
*/
private int sweepIndex = 0;
/**
* 交換執行動畫的顏色數組
*/
private int[] colors = new int[]{getResources().getColor(R.color.colorYellow),
getResources().getColor(R.color.colorRed),
getResources().getColor(R.color.colorBlue)};
/**
* 動畫所執行的最大偏移量(即中間點和最左邊的距離)
*/
private Float maxWidth = 200f;
/**
* 三個圓的半徑
*/
private Float radius = 30f;
/**
* 當前偏移的X座標
*/
private Float currentX = 0f;
/**
* 畫筆
*/
private Paint paint;
/**
* 屬性動畫
*/
private ValueAnimator valueAnimator;
public BaiduProgressBar2(Context context) {
super(context);
startAnimator();
}
public BaiduProgressBar2(Context context, AttributeSet attrs) {
super(context, attrs);
startAnimator();
}
public BaiduProgressBar2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
startAnimator();
}
/**
* 用屬性動畫實現位移動畫
*/
private void startAnimator() {
valueAnimator = ValueAnimator.ofFloat(0f, maxWidth, 0);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentX = (Float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.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) {
sweep(sweepIndex);
}
});
valueAnimator.setInterpolator(new LinearInterpolator());
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
valueAnimator.setRepeatCount(-1);
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.setDuration(1000);
valueAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
/**畫左邊的圓**/
paint.setColor(colors[0]);
canvas.drawCircle(centerX - currentX, centerY, radius, paint);
/**畫右邊的圓**/
paint.setColor(colors[1]);
canvas.drawCircle(centerX + currentX, centerY, radius, paint);
/**畫中間的圓**/
paint.setColor(colors[2]);
canvas.drawCircle(centerX, centerY, radius, paint);
}
/**
* 每次讓先執行動畫的目標和中間停止的動畫目標交換
*
* @param a 最先執行的動畫的索引
*/
private void sweep(int a) {
int temp = colors[2];
colors[2] = colors[a];
colors[a] = temp;
if (a == 0) {
sweepIndex = 1;
} else {
sweepIndex = 0;
}
}
/**
* 在View銷燬時停止動畫
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
valueAnimator.cancel();
}
}
在經過以上的動畫之後,突然在Loading設計思路分享中看到了兩個比較酷炫的動畫
主要思路圖如下
第三個:扔球動畫->水平旋轉動畫
package cn.bluemobi.dylan.baiduprogressbar;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by dylan on 2016-12-04.
*/
public class BaiduLoadingView extends FrameLayout {
/**
* 存放三個小球的集合
*/
private List<ImageView> views = new ArrayList<>();
/**
* 同時播放動畫的對象
*/
private AnimatorSet animatorSet;
public BaiduLoadingView(Context context) {
super(context);
init();
}
public BaiduLoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BaiduLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void assignViews() {
ImageView iv_blue = (ImageView) findViewById(R.id.iv_blue);
ImageView iv_yellow = (ImageView) findViewById(R.id.iv_yellow);
ImageView iv_red = (ImageView) findViewById(R.id.iv_red);
views.add(iv_yellow);
views.add(iv_red);
views.add(iv_blue);
}
/**
* 初始化
*/
private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.baidu_progress_bar, this, true);
assignViews();
startAnimator();
}
private void startAnimator() {
/**動畫組合->讓左右同時執行**/
animatorSet = new AnimatorSet();
animatorSet.play(startAnimator1()).with(startAnimator2()).with(startAnimator3());
animatorSet.setInterpolator(new LinearInterpolator());
animatorSet.start();
}
private ObjectAnimator startAnimator1() {
/**對象的不同屬性組合**/
PropertyValuesHolder objectAnimatorTranslation = PropertyValuesHolder.ofFloat("translationX", -100, -200, -100, 0, 100, 200, 100, 0, -100);
PropertyValuesHolder objectAnimatorScale = PropertyValuesHolder.ofFloat("scaleX", 0.5f, 1, 1.5f, 1, 0.5f, 1, 1.5f, 1, 0.5f);
PropertyValuesHolder objectAnimatorScaleY = PropertyValuesHolder.ofFloat("scaleY", 0.5f, 1, 1.5f, 1, 0.5f, 1, 1.5f, 1, 0.5f);
/**同時操作對象的兩個屬性動畫**/
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(views.get(0), objectAnimatorTranslation, objectAnimatorScale, objectAnimatorScaleY);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setDuration(2000);
objectAnimator.start();
return objectAnimator;
}
private ObjectAnimator startAnimator2() {
/**對象的不同屬性組合**/
PropertyValuesHolder objectAnimatorTranslation = PropertyValuesHolder.ofFloat("translationX", 0, 100, 200, 100, 0, -100, -200, -100, 0);
PropertyValuesHolder objectAnimatorScale = PropertyValuesHolder.ofFloat("scaleX", 1, 0.5f, 1, 1.5f, 1, 0.5f, 1, 1.5f, 1);
PropertyValuesHolder objectAnimatorScaleY = PropertyValuesHolder.ofFloat("scaleY", 1, 0.5f, 1, 1.5f, 1, 0.5f, 1, 1.5f, 1);
/**同時操作對象的兩個屬性動畫**/
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(views.get(1), objectAnimatorTranslation, objectAnimatorScale, objectAnimatorScaleY);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setDuration(2000);
objectAnimator.start();
return objectAnimator;
}
private ObjectAnimator startAnimator3() {
/**對象的不同屬性組合**/
PropertyValuesHolder objectAnimatorTranslation = PropertyValuesHolder.ofFloat("translationX", 100, 0, -100, -200, -100, 0, 100, 200, 100);
PropertyValuesHolder objectAnimatorScale = PropertyValuesHolder.ofFloat("scaleX", 1.5f, 1f, 0.5f, 1, 1.5f, 1, 0.5f, 1, 1.5f);
PropertyValuesHolder objectAnimatorScaleY = PropertyValuesHolder.ofFloat("scaleY", 1.5f, 1f, 0.5f, 1, 1.5f, 1, 0.5f, 1, 1.5f);
/**同時操作對象的兩個屬性動畫**/
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(views.get(2), objectAnimatorTranslation, objectAnimatorScale, objectAnimatorScaleY);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setDuration(2000);
objectAnimator.start();
return objectAnimator;
}
/**
* 在View銷燬時停止動畫
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
animatorSet.cancel();
}
}
第四個:扔球動畫->垂直旋轉動畫
package cn.bluemobi.dylan.baiduprogressbar;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by dylan on 2016-12-04.
*/
public class BaiduProgressLoading extends FrameLayout {
/**
* 存放三個小球的集合
*/
private List<ImageView> views = new ArrayList<>();
public BaiduProgressLoading(Context context) {
super(context);
init();
}
public BaiduProgressLoading(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BaiduProgressLoading(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void assignViews() {
ImageView iv_blue = (ImageView) findViewById(R.id.iv_blue);
ImageView iv_yellow = (ImageView) findViewById(R.id.iv_yellow);
ImageView iv_red = (ImageView) findViewById(R.id.iv_red);
views.add(iv_yellow);
views.add(iv_red);
views.add(iv_blue);
}
private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.baidu_progress_bar, this, true);
assignViews();
startAnimator1();
startAnimator2();
startAnimator3();
}
PointF point = new PointF();
private void startAnimator1() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(90, 360);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 - 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(0).setTranslationX(point.x);
views.get(0).setTranslationY(point.y);
}
});
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setDuration(750);
valueAnimator.start();
ValueAnimator valueAnimator2 = ValueAnimator.ofFloat(180, 0, -180);
valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 + 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(0).setTranslationX(point.x);
views.get(0).setTranslationY(point.y);
}
});
valueAnimator2.setInterpolator(new LinearInterpolator());
valueAnimator2.setDuration(1000);
valueAnimator2.setStartDelay(750);
valueAnimator2.start();
ValueAnimator valueAnimator3 = ValueAnimator.ofFloat(0, 90);
valueAnimator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 - 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(0).setTranslationX(point.x);
views.get(0).setTranslationY(point.y);
}
});
valueAnimator3.setInterpolator(new LinearInterpolator());
valueAnimator3.setDuration(250);
valueAnimator3.setStartDelay(1750);
valueAnimator3.start();
valueAnimator3.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
startAnimator1();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
private void startAnimator2() {
ValueAnimator valueAnimator2 = ValueAnimator.ofFloat(180, 0, -180);
valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 + 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(1).setTranslationX(point.x);
views.get(1).setTranslationY(point.y);
}
});
valueAnimator2.setInterpolator(new LinearInterpolator());
valueAnimator2.setDuration(1000);
valueAnimator2.start();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 360);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 - 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(1).setTranslationX(point.x);
views.get(1).setTranslationY(point.y);
}
});
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setDuration(1000);
valueAnimator.setStartDelay(1000);
valueAnimator.start();
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
startAnimator2();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
private void startAnimator3() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(270, 180);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 + 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(2).setTranslationX(point.x);
views.get(2).setTranslationY(point.y);
}
});
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setDuration(250);
valueAnimator.start();
ValueAnimator valueAnimator2 = ValueAnimator.ofFloat(0, 360);
valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 - 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(2).setTranslationX(point.x);
views.get(2).setTranslationY(point.y);
}
});
valueAnimator2.setInterpolator(new LinearInterpolator());
valueAnimator2.setDuration(1000);
valueAnimator2.setStartDelay(250);
valueAnimator2.start();
ValueAnimator valueAnimator3 = ValueAnimator.ofFloat(180, -90);
valueAnimator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
/**
*
* 圓點座標:(x0,y0)
* 半徑:r
* 角度:a0
* 則圓上任一點爲:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
*/
/**第四步,根據每個菜單真實角度計算其座標值**/
point.x = (float) Math.cos(value * (Math.PI / 180)) * 100 + 100;
point.y = (float) -Math.sin(value * (Math.PI / 180)) * 100;
views.get(2).setTranslationX(point.x);
views.get(2).setTranslationY(point.y);
}
});
valueAnimator3.setInterpolator(new LinearInterpolator());
valueAnimator3.setDuration(750);
valueAnimator3.setStartDelay(1250);
valueAnimator3.start();
valueAnimator3.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
startAnimator3();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
}