天天看點

【安卓-動畫】使用ObjectAnimator實作ArcMenu動畫效果

使用ObjectAnimator實作ArcMenu動畫效果

ObjectAnimator是Google3.0+系統提供的另一套動畫架構,相比于原始的Animation動畫架構,ObjectAnimator(屬性動畫)更靈活、友善且效率更高。

使用普通的Animation架構,如果我們需要實作一個ImageView的移動效果,可以使用TranslateAnimation很輕松的”實作”,這裡所說的實作是指界面層次的,但是這種僅停留在界面層次的”實作”會出現很多的問題,例如我們用TranslateAnimation把ImageView從A點移動到了B點,但其實移動後的ImageView的響應事件如點選時間等,依然停留在移動前的A點。換句話說,使用Animation架構實作的效果停留在”界面”層次而非”互動層次”。

對于ObjectAnimator的詳細介紹,大家可以參考其他的博文了解,在此不在詳細說明。

我們要實作的效果大緻是這樣的:

【安卓-動畫】使用ObjectAnimator實作ArcMenu動畫效果

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移動的位置是需要一些數學計算的,以下圖做解釋:

【安卓-動畫】使用ObjectAnimator實作ArcMenu動畫效果

通過上圖的原理,再作一些簡單的計算,就能夠得到每個圖檔移動後的位置

x=radius*Math.cos(α);

y=radius*Math.sin(α);

代碼中,showArcMenu表示菜單展開的方法,closeArcMenu表示菜單收回的方法,這兩個動作的動畫恰好是相反的,隻是起始x,y和終止x,y調換了一下位置而已。

寫博文不容易,用Photoshop畫示意圖更是蛋疼,希望該博文會有所幫助。

繼續閱讀