使用ObjectAnimator實作ArcMenu動畫效果
ObjectAnimator是Google3.0+系統提供的另一套動畫架構,相比于原始的Animation動畫架構,ObjectAnimator(屬性動畫)更靈活、友善且效率更高。
使用普通的Animation架構,如果我們需要實作一個ImageView的移動效果,可以使用TranslateAnimation很輕松的”實作”,這裡所說的實作是指界面層次的,但是這種僅停留在界面層次的”實作”會出現很多的問題,例如我們用TranslateAnimation把ImageView從A點移動到了B點,但其實移動後的ImageView的響應事件如點選時間等,依然停留在移動前的A點。換句話說,使用Animation架構實作的效果停留在”界面”層次而非”互動層次”。
對于ObjectAnimator的詳細介紹,大家可以參考其他的博文了解,在此不在詳細說明。
我們要實作的效果大緻是這樣的:
PS:不會用錄屏軟體做gif,隻能拿一張效果圖充數,見諒===
布局檔案中很簡單,一個FrameLayout包含6個ImageView,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#ffffff"
android:padding="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_camera"
android:id="@+id/iv_camera"/>
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_music"
android:id="@+id/iv_music"/>
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_place"
android:id="@+id/iv_place"/>
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_sleep"
android:id="@+id/iv_sleep"/>
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_thought"
android:id="@+id/iv_thought"/>
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_with"
android:id="@+id/iv_with"/>
</FrameLayout>
這篇部落格的主要目的是用ObjectAnimator實作動畫效果,是以并沒有吧ArcMenu抽成自定義View。
ArcMenuActivity中的代碼如下:
package com.example.myview;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.BounceInterpolator;
import android.widget.ImageView;
import android.widget.Toast;
import java.util.LinkedList;
import java.util.List;
/**
* Created by WangChunLei on 15/10/31.
*/
public class ArcMenuActivity extends Activity implements View.OnClickListener {
int[] resId = {R.id.iv_camera, R.id.iv_music, R.id.iv_place, R.id.iv_sleep, R.id.iv_thought, R.id.iv_with};
List<ImageView> list = new LinkedList<ImageView>();
boolean isShowing = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_arc_menu);
for (int i = ; i < resId.length; i++) {
ImageView iv = (ImageView) findViewById(resId[i]);
list.add(iv);
iv.setOnClickListener(this);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_with:
if (isShowing) {//收回
closeArcMenu();
} else {//彈出
showArcMenu();
}
isShowing = !isShowing;
break;
case R.id.iv_thought:
case R.id.iv_camera:
case R.id.iv_sleep:
case R.id.iv_music:
case R.id.iv_place:
Toast.makeText(this, "目前點選的圖檔ID為:" + v.getId(), Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
private void showArcMenu() {
int radius = (list.size() - ) * ;//半徑
float perAngle = (float) (( / (list.size() - )) * Math.PI / );
for (int i = ; i < list.size() - ; i++) {
float x = (float) (radius * Math.cos(i * perAngle));
float y = (float) (radius * Math.sin(i * perAngle));
ObjectAnimator animator1 = ObjectAnimator.ofFloat(list.get(i),
"translationY", f, x);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(list.get(i),
"translationX", f, y);
AnimatorSet set = new AnimatorSet();
set.playTogether(animator1, animator2);
set.setDuration();
set.setInterpolator(new BounceInterpolator());
set.setStartDelay(i * );
set.start();
}
}
private void closeArcMenu() {
int radius = (list.size() - ) * ;//半徑
float perAngle = (float) (( / (list.size() - )) * Math.PI / );
for (int i = ; i < list.size() - ; i--) {
float x = (float) (radius * Math.cos(i * perAngle));
float y = (float) (radius * Math.sin(i * perAngle));
ObjectAnimator animator1 = ObjectAnimator.ofFloat(list.get(i), "translationY", x, f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(list.get(i), "translationX", y, f);
AnimatorSet set = new AnimatorSet();
set.playTogether(animator1, animator2);
set.setDuration();
set.setInterpolator(new BounceInterpolator());
set.setStartDelay(i * );
set.start();
}
}
}
每個ImageView移動的位置是需要一些數學計算的,以下圖做解釋:
通過上圖的原理,再作一些簡單的計算,就能夠得到每個圖檔移動後的位置
x=radius*Math.cos(α);
y=radius*Math.sin(α);
代碼中,showArcMenu表示菜單展開的方法,closeArcMenu表示菜單收回的方法,這兩個動作的動畫恰好是相反的,隻是起始x,y和終止x,y調換了一下位置而已。
寫博文不容易,用Photoshop畫示意圖更是蛋疼,希望該博文會有所幫助。