在上篇文章中,我們已經介紹了屬性動畫的基本用法:http://blog.csdn.net/u010838555/article/details/76214821
這裡做一個執行個體-----扇形菜單~

#1.我們首先要用到一個屬性動畫 以下是實作一個最基本的簡單的對imageView的x坐标和y坐标進行移動的動畫。
/**
* 第一個參數代表要操作的對象
* 第二個參數代表要操作的對象的屬性
* 第三個參數代表要操作的對象的屬性的起始值
* 第四個參數代表要操作的對象的屬性的終止值
*/
ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews, "translationX", 0, 500);
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews, "translationY", 0, 500);
/**動畫集合,用來編排動畫**/
AnimatorSet animatorSet = new AnimatorSet();
/**設定動畫時長**/
animatorSet.setDuration(500);
/**設定同時播放x方向的位移動畫和y方向的位移動畫**/
animatorSet.play(objectAnimatorX).with(objectAnimatorY);
/**開始播放動畫**/
animatorSet.start();
#2.如何擷取菜單展開的坐标,先複習下數學
這個是我的手稿,畫的比較粗糙,請大家見諒
#3.如何用代碼計算,計算公式
我們由上圖可以推導出計算公式如下:
圓點坐标:(x0,y0)
半徑:r
角度:a0
則圓上任一點為:(x1,y1)
x1 = x0 + r * cos(ao * 3.14 /180 )
y1 = y0 + r * sin(ao * 3.14 /180 )
#4.代碼實作
總共分為五步,代碼如下:
/**
* 顯示扇形菜單
*/
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
private void showSectorMenu() {
/***第一步,周遊所要展示的菜單ImageView*/
for (int i = 0; i < imageViews.size(); i++) {
PointF point = new PointF();
/***第二步,根據菜單個數計算每個菜單之間的間隔角度*/
int avgAngle = (90 / (imageViews.size() - 1));
/**第三步,根據間隔角度計算出每個菜單相對于水準線起始位置的真實角度**/
int angle = avgAngle * i;
Log.d(TAG, "angle=" + angle);
/**
*
* 圓點坐标:(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(angle * (Math.PI / 180)) * radius1;
point.y = (float) -Math.sin(angle * (Math.PI / 180)) * radius1;
Log.d(TAG, point.toString());
/**第五步,根據坐标執行位移動畫**/
/**
* 第一個參數代表要操作的對象
* 第二個參數代表要操作的對象的屬性
* 第三個參數代表要操作的對象的屬性的起始值
* 第四個參數代表要操作的對象的屬性的終止值
*/
ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews.get(i), "translationX", 0, point.x);
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews.get(i), "translationY", 0, point.y);
/**動畫集合,用來編排動畫**/
AnimatorSet animatorSet = new AnimatorSet();
/**設定動畫時長**/
animatorSet.setDuration(500);
/**設定同時播放x方向的位移動畫和y方向的位移動畫**/
animatorSet.play(objectAnimatorX).with(objectAnimatorY);
/**開始播放動畫**/
animatorSet.start();
}
}
#5.如何關閉菜單
啟示關閉菜單和打開菜單的操作是相反的,隻需要将起始坐标和終止坐标調換就可以了。
/**
* 關閉扇形菜單
*/
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
private void closeSectorMenu() {
for (int i = 0; i < imageViews.size(); i++) {
PointF point = new PointF();
int avgAngle = (90 / (imageViews.size() - 1));
int angle = avgAngle * i;
Log.d(TAG, "angle=" + angle);
point.x = (float) Math.cos(angle * (Math.PI / 180)) * radius1;
point.y = (float) -Math.sin(angle * (Math.PI / 180)) * radius1;
Log.d(TAG, point.toString());
ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews.get(i), "translationX", point.x, 0);
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews.get(i), "translationY", point.y, 0);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.play(objectAnimatorX).with(objectAnimatorY);
animatorSet.start();
}
}
#6.菜單按鈕的旋轉動畫
其實就是打開菜單時進行45°旋轉,關閉的時候再旋轉會原來的0°;
Boolean isShowing = (Boolean) iv1.getTag();
if (null == isShowing || isShowing == false) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv1, "rotation", 0, 45);
objectAnimator.setDuration(500);
objectAnimator.start();
iv1.setTag(true);
showSectorMenu();
} else {
iv1.setTag(false);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv1, "rotation", 45, 0);
objectAnimator.setDuration(500);
objectAnimator.start();
closeSectorMenu();
}
#7.圓形菜單 圓形菜單其實就是對360度進行等分,原理一樣,代碼如下:
/**
* 顯示圓形菜單
*/
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
private void showCircleMenu() {
for (int i = 0; i < imageViews2.size(); i++) {
PointF point = new PointF();
int avgAngle = (360 / (imageViews2.size() - 1));
int angle = avgAngle * i;
Log.d(TAG, "angle=" + angle);
point.x = (float) Math.cos(angle * (Math.PI / 180)) * radius2;
point.y = (float) Math.sin(angle * (Math.PI / 180)) * radius2;
Log.d(TAG, point.toString());
ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews2.get(i), "translationX", 0, point.x);
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews2.get(i), "translationY", 0, point.y);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.play(objectAnimatorX).with(objectAnimatorY);
animatorSet.start();
}
}
/**
* 關閉圓形菜單
*/
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
private void closeCircleMenu() {
for (int i = 0; i < imageViews2.size(); i++) {
PointF point = new PointF();
int avgAngle = (360 / (imageViews2.size() - 1));
int angle = avgAngle * i;
Log.d(TAG, "angle=" + angle);
point.x = (float) Math.cos(angle * (Math.PI / 180)) * radius2;
point.y = (float) Math.sin(angle * (Math.PI / 180)) * radius2;
Log.d(TAG, point.toString());
ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews2.get(i), "translationX", point.x, 0);
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews2.get(i), "translationY", point.y, 0);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.play(objectAnimatorX).with(objectAnimatorY);
animatorSet.start();
}
}
源碼:http://download.csdn.net/detail/u010838555/9913004