Android “+”号发散菜单动画的实现--- pathMenu的实现思路

一,引言

最近有需求,需要开发类似淘宝“问大家”进去中间那个“+”号Tab,点击散发出两个菜单按钮的动画,大概效果如下:
这里写图片描述

然后点击“+”做发散动画,效果大概如下

这里写图片描述
这里写图片描述
这里写图片描述

对于这样子的动效是很多主流app都在做的,那么我们应该怎么做呢?

二,那么怎么实现这个动画呢

下面让我来讲讲要怎么实现这样子的pathMenu动画
先借助前辈的一张图来讲讲扇形原理:
这里写图片描述

这款扇形菜单实现的也是非常的好,提供半径 radius 设置和 位置 position设置
其实说白了就是定好相隔两个菜单之间的夹角以及菜单运动到的高度。
回到原点,我们上面的效果图怎么实现,下面看代码,都有注释:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:zhy="http://schemas.android.com/apk/res-auto">
    <ImageView
        android:id="@+id/iv_icon3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:alpha="0"
        android:src="@drawable/a3" />
    <ImageView
        android:id="@+id/iv_icon4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:alpha="0"
        android:src="@drawable/a4" />
    <ImageView
        android:id="@+id/iv_icon6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/stay"
        android:layout_marginBottom="20dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

即想把三张图片叠加在一起

package demo.wuchunmei.com.pathmenudemo;

import android.app.Activity;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.BounceInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {
    private ImageView mIvIcon1;
    private ImageView mIvIcon2;
    private ImageView mIvBtn;
    private boolean mIsOpen = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initView();
    }

    /**
     * 初始化视图
     */
    private void initView() {
        setContentView(R.layout.activity_main);
        mIvIcon1 = (ImageView) findViewById(R.id.iv_icon3);
        mIvIcon2 = (ImageView) findViewById(R.id.iv_icon4);
        mIvBtn = (ImageView) findViewById(R.id.iv_icon6);
        mIvBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mIsOpen) {
                    showIcon();
                    mIsOpen = false;
                } else {
                    closeIcon();
                    mIsOpen = true;
                }
            }
        });
    }


    /**
     * 动画实现,因为都有角度,所有,要有三角函数计算
     * 使图标位移距离相等,实现扇形效果
     */
     private void showIcon() {
        //设置动画时间
        int duration = 600;
        //动画距离,屏幕宽度的30%
        float distance = getScreenWidth()*0.3f;
        //相邻ImageView运动角度式22.5度
//        float angle1 = (float)(22.5f*Math.PI/180);
        float angle2 = (float)(135f*Math.PI/180);
        float angle3 = (float)(45.5f*Math.PI/180);

         //icon1
//         PropertyValuesHolder p31 = PropertyValuesHolder.ofFloat("TranslationX", 0f, (float) (distance * Math.cos(angle2)));
//         PropertyValuesHolder p32 = PropertyValuesHolder.ofFloat("TranslationY", 0f, -(float) (distance * Math.sin(angle2)));
//         //icon2
//         PropertyValuesHolder p41 = PropertyValuesHolder.ofFloat("TranslationX", 0f, (float) (distance * Math.cos(angle3)));
//         PropertyValuesHolder p42 = PropertyValuesHolder.ofFloat("TranslationY", 0f, -(float) (distance * Math.sin(angle3)));
//         PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha",0f,1f);
//         PropertyValuesHolder rota = PropertyValuesHolder.ofFloat("rotation", 0f, 45f);
//         PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.4f);
//         PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.4f);
//         ObjectAnimator animator3 = ObjectAnimator.ofPropertyValuesHolder(mIvIcon1, alpha, p31, p32);
//         ObjectAnimator animator4 = ObjectAnimator.ofPropertyValuesHolder(mIvIcon2, alpha, p41, p42);
//         ObjectAnimator animator6 = ObjectAnimator.ofPropertyValuesHolder(mIvBtn, rota, scaleX, scaleY);
//         AnimatorSet animatorSet = new AnimatorSet();
//         animatorSet.setDuration(duration);
//         animatorSet.setInterpolator(getInterpolator(0.2f, 1f, 0.2f, 1f));
//         animatorSet.playTogether(animator6, animator3, animator4);
//         animatorSet.start();
         Interpolator interpolator = getInterpolator(0.2f, 1f, 0.2f, 1f);
         float translationX_icon1 = (float) (distance * Math.cos(angle2));
         float translationY_icon1 = -(float) (distance * Math.sin(angle2));
         float translationX_icon2 = (float) (distance * Math.cos(angle3));
         float translationY_icon2 = -(float) (distance * Math.sin(angle3));
         mIvBtn.animate().rotation(45f).scaleX(0.4f).scaleY(0.4f).setDuration(duration).setInterpolator(interpolator);
         mIvIcon1.animate().alpha(1).translationX(translationX_icon1).translationY(translationY_icon1)
                 .setDuration(duration).setInterpolator(interpolator);
         mIvIcon2.animate().alpha(1).translationX(translationX_icon2).translationY(translationY_icon2)
                 .setDuration(duration).setInterpolator(interpolator);
    }


    private void closeIcon() {

        //设置动画时间
        int duration = 600;
        //动画距离,屏幕宽度的60%
        float distance = getScreenWidth()*0.3f;
        //相邻ImageView运动角度式22.5度
//        float angle1 = (float)(22.5f*Math.PI/180);
        float angle2 = (float)(135f*Math.PI/180);
        float angle3 = (float)(45.5f*Math.PI/180);

        //icon1
//        PropertyValuesHolder p31 = PropertyValuesHolder.ofFloat("TranslationX", (float) (distance * Math.cos(angle2)),0f);
//        PropertyValuesHolder p32 = PropertyValuesHolder.ofFloat("TranslationY",-(float) (distance * Math.sin(angle2)), 0f);
//        //icon2
//        PropertyValuesHolder p41 = PropertyValuesHolder.ofFloat("TranslationX",(float) (distance * Math.cos(angle3)), 0f);
//        PropertyValuesHolder p42 = PropertyValuesHolder.ofFloat("TranslationY",  -(float) (distance * Math.sin(angle3)),0f);
//        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha",1f,0f);
//        PropertyValuesHolder rota = PropertyValuesHolder.ofFloat("rotation",45f, 0f);
//        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX",0.4f, 1f);
//        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.4f,1f);
//        ObjectAnimator animator3 = ObjectAnimator.ofPropertyValuesHolder(mIvIcon1, alpha, p31, p32);
//        ObjectAnimator animator4 = ObjectAnimator.ofPropertyValuesHolder(mIvIcon2, alpha, p41, p42);
//        ObjectAnimator animator6 = ObjectAnimator.ofPropertyValuesHolder(mIvBtn, rota, scaleX, scaleY);
//
//        AnimatorSet animatorSet = new AnimatorSet();
//        animatorSet.setDuration(duration);
//        animatorSet.setInterpolator(getInterpolator(0.33f,0f,0.12f,1f));
//        animatorSet.playTogether(animator6,animator3,animator4);
//        animatorSet.start();

        Interpolator interpolator = getInterpolator(0.2f, 1f, 0.2f, 1f);
        mIvBtn.animate().rotation(0f).scaleX(1f).scaleY(1f).setDuration(duration).setInterpolator(interpolator);
        mIvIcon1.animate().alpha(0).translationX(0).translationY(0).setDuration(duration).setInterpolator(interpolator);
        mIvIcon2.animate().alpha(0).translationX(0).translationY(0).setDuration(duration).setInterpolator(interpolator);
    }

    /**
     * 竖屏时获取屏幕宽度,横屏时,获取高度
     * @return
     */
    public int getScreenWidth(){
        DisplayMetrics outMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
        int x = outMetrics.widthPixels;
        int y = outMetrics.heightPixels;
        return x>y?y:x;
    }

    /**
     * 自定义动画差值器
     * @param x1
     * @param x2
     * @param y1
     * @param y2
     * @return
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private Interpolator getInterpolator(float x1, float x2, float y1, float y2) {
        final int version = Build.VERSION.SDK_INT;
        if (version >= 21) {
            return new PathInterpolator(x1, x2, y1, y2);
        } else {
            return new LinearInterpolator();
        }
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值