【安卓-动画】使用ObjectAnimator实现ArcMenu动画效果

使用ObjectAnimator实现ArcMenu动画效果

ObjectAnimator是Google3.0+系统提供的另一套动画框架,相比于原始的Animation动画框架,ObjectAnimator(属性动画)更灵活、方便且效率更高。

使用普通的Animation框架,如果我们需要实现一个ImageView的移动效果,可以使用TranslateAnimation很轻松的”实现”,这里所说的实现是指界面层次的,但是这种仅停留在界面层次的”实现”会出现很多的问题,例如我们用TranslateAnimation把ImageView从A点移动到了B点,但其实移动后的ImageView的响应事件如点击时间等,依然停留在移动前的A点。换句话说,使用Animation框架实现的效果停留在”界面”层次而非”交互层次”。

对于ObjectAnimator的详细介绍,大家可以参考其他的博文了解,在此不在详细说明。

我们要实现的效果大致是这样的:
【安卓-动画】使用ObjectAnimator实现ArcMenu动画效果_第1张图片

PS:不会用录屏软件做gif,只能拿一张效果图充数,见谅===

布局文件中很简单,一个FrameLayout包含6个ImageView,代码如下:


<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 list = new LinkedList();
    boolean isShowing = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_arc_menu);

        for (int i = 0; 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() - 2) * 120;//半径
        float perAngle = (float) ((90 / (list.size() - 2)) * Math.PI / 180);

        for (int i = 0; i < list.size() - 1; 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", 0f, x);
            ObjectAnimator animator2 = ObjectAnimator.ofFloat(list.get(i),
                    "translationX", 0f, y);

            AnimatorSet set = new AnimatorSet();
            set.playTogether(animator1, animator2);
            set.setDuration(300);
            set.setInterpolator(new BounceInterpolator());
            set.setStartDelay(i * 100);
            set.start();
        }
    }

    private void closeArcMenu() {
        int radius = (list.size() - 2) * 120;//半径
        float perAngle = (float) ((90 / (list.size() - 2)) * Math.PI / 180);

        for (int i = 0; i < list.size() - 1; 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, 0f);
            ObjectAnimator animator2 = ObjectAnimator.ofFloat(list.get(i), "translationX", y, 0f);

            AnimatorSet set = new AnimatorSet();
            set.playTogether(animator1, animator2);
            set.setDuration(300);
            set.setInterpolator(new BounceInterpolator());
            set.setStartDelay(i * 100);
            set.start();
        }
    }
}

每个ImageView移动的位置是需要一些数学计算的,以下图做解释:

【安卓-动画】使用ObjectAnimator实现ArcMenu动画效果_第2张图片
通过上图的原理,再作一些简单的计算,就能够得到每个图片移动后的位置
x=radius*Math.cos(α);
y=radius*Math.sin(α);

代码中,showArcMenu表示菜单展开的方法,closeArcMenu表示菜单收回的方法,这两个动作的动画恰好是相反的,只是起始x,y和终止x,y调换了一下位置而已。

写博文不容易,用Photoshop画示意图更是蛋疼,希望该博文会有所帮助。

你可能感兴趣的:(【安卓-动画】)