属性动画的研究——多级菜单展开


layout: post
title: 属性动画的研究——多级菜单展开
date: 2017-07-26 16:33:11
tags:

  • Android开发
    categories:
  • Android开发

很久都没有更新博客了,之前一直忙着参加挑战杯,然后就是期末考试,再然后在室友的乱带节奏下准备找实习。现在找到了一份实习工作,老大还在给新项目打框架,让我先研究下动画,说是后面会用到,就忙里偷闲玩demo

  • 是看imooc上面的一个大神的课程-http://www.imooc.com/learn/263。讲的很nice,然后我就继续深入了一点点,完善了demo而已。

效果图

[外链图片转存失败(img-DYBKk8KJ-1562312416902)(https://pic.sorgs.cn/属性动画_菜单展开.gif)]https://pic.sorgs.cn/属性动画_菜单展开.gif)

分析

  • 首先是采用了属性动画的方式
    • 在x和y上面做手脚去变化坐标
 PropertyValuesHolder Y, X;
            //设置动画
            Y = PropertyValuesHolder.ofFloat("translationY", y);
            X = PropertyValuesHolder.ofFloat("translationX", x);

            //添加动画集合
            ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageViewList.get(i), X, Y);
  • 然后是两个动画一起
  • 使用抖动效果(使用了BounceInterpolator)[可能gif有些看不出来]
 //为控件增加自由落体动画效果
            animator.setInterpolator(new BounceInterpolator());

计算坐标

我们的展开是一个半圆的扇形,那么肯定就是利用数学函数来进行计算,如图

[外链图片转存失败(img-rvcOlo1I-1562312480703)(https://pic.sorgs.cn/属性动画_菜单展开说明.jpg)]

从上面到下面,x是从最大到0,y是从0到最大
每一个点的坐标就是根据圆心角来计算

//需要扩散的角度 以180度为例
            float angle = (float) (Math.PI * 180 / 180);

            //计算偏移的x,y坐标
            x = (float) (n * Math.sin(angle / (res.length - 1) * count));
            y = (float) (n * Math.cos(angle / (res.length - 1) * count));

完整代码

  • 布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <ImageView
        android:id="@+id/iv_h"
        style="@style/ImageView"
        android:src="@mipmap/h"/>

    <ImageView
        android:id="@+id/iv_g"
        style="@style/ImageView"
        android:src="@mipmap/g"/>

    <ImageView
        android:id="@+id/iv_f"
        style="@style/ImageView"
        android:src="@mipmap/f"/>

    <ImageView
        android:id="@+id/iv_e"
        style="@style/ImageView"
        android:src="@mipmap/e"/>

    <ImageView
        android:id="@+id/iv_d"
        style="@style/ImageView"
        android:src="@mipmap/d"/>

    <ImageView
        android:id="@+id/iv_c"
        style="@style/ImageView"
        android:src="@mipmap/c"/>

    <ImageView
        android:id="@+id/iv_b"
        style="@style/ImageView"
        android:src="@mipmap/b"/>

    <ImageView
        android:id="@+id/iv_a"
        style="@style/ImageView"
        android:src="@mipmap/a"/>

</RelativeLayout>
  • 抽取的属性
    <style name="ImageView">
        <item name="android:layout_width">50dp</item>
        <item name="android:layout_height">50dp</item>
        <item name="android:paddingLeft">5dp</item>
        <item name="android:paddingTop">5dp</item>
    </style>
  • 逻辑
package com.sorgs.animtest;

import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.BounceInterpolator;
import android.widget.ImageView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private int[] res = {R.id.iv_a, R.id.iv_b, R.id.iv_c, R.id.iv_d, R.id.iv_e, R.id.iv_f, R.id.iv_g, R.id.iv_h};
    private List<ImageView> imageViewList = new ArrayList<>();
    /**
     * 菜单打开或者关闭的标志
     */
    private boolean flag = true;

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

        for (int re : res) {
            //循环添加每个控件
            ImageView imageView = (ImageView) findViewById(re);
            //为每个控件添加点击事件
            imageView.setOnClickListener(this);
            //将每个控件添加到List中
            imageViewList.add(imageView);
        }

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.iv_a:
                if (flag) {
                    startAnim();
                } else {
                    emdAnim();
                }

                break;
            default:
                //点击其他按钮,弹出toast
                Toast.makeText(getApplication(), "click" + view.getId(), Toast.LENGTH_SHORT).show();
                break;
        }

    }

    /**
     * 关闭菜单动画
     */
    private void emdAnim() {
        for (int i = 1; i < res.length; i++) {
            PropertyValuesHolder Y, X;
            //X Y 都回归原点
            Y = PropertyValuesHolder.ofFloat("translationY", 0);
            X = PropertyValuesHolder.ofFloat("translationX", 0);
            ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageViewList.get(i), X, Y);

            //设置动画执行时间
            animator.setDuration(500);
            //每个控件之间的延时,形成每个按钮依次出现
            animator.setStartDelay(i * 300);
            //为控件增加自由落体动画效果
            animator.setInterpolator(new BounceInterpolator());
            //执行动画
            animator.start();
            //重置flag
            flag = true;
        }
    }


    /**
     * 打开菜单动画
     */
    private void startAnim() {

        //扩散的距离,获取控件的高度的2倍
        float x, y, n = imageViewList.get(0).getMeasuredHeight() * 2;

        for (int i = 1; i < res.length; i++) {
            int count = res.length - i;
            //需要扩散的角度 以180度为例
            float angle = (float) (Math.PI * 180 / 180);

            //计算偏移的x,y坐标
            x = (float) (n * Math.sin(angle / (res.length - 1) * count));
            y = (float) (n * Math.cos(angle / (res.length - 1) * count));

            PropertyValuesHolder Y, X;
            //设置动画
            Y = PropertyValuesHolder.ofFloat("translationY", y);
            X = PropertyValuesHolder.ofFloat("translationX", x);

            //添加动画集合
            ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageViewList.get(i), X, Y);

            //设置动画执行时间
            animator.setDuration(500);
            //每个控件之间的延时,形成每个按钮依次出现
            animator.setStartDelay(i * 300);
            //为控件增加自由落体动画效果
            animator.setInterpolator(new BounceInterpolator());
            //执行动画
            animator.start();
            //重置flag
            flag = false;
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值