menu展开动画(属性动画)

好伤心啊,webm转化成的pdf在上居然无法正常播放,我要怎么给宝宝们展示动态效果呢,蓝瘦香菇...上截图~~


menu展开动画(属性动画)_第1张图片
Screenshot_1561041389.png
menu展开动画(属性动画)_第2张图片
Screenshot_1561041395.png
menu展开动画(属性动画)_第3张图片
Screenshot_1561041444.png

嗯啦嗯啦,安啦,那个在冒烟儿,是均匀分布的啦!
怎么实现的呢?so easy!
布局首先是个FrameLayout,里面有包含8个imageview,一起堆在左上角,布局文件如下:




    

    

    

    

    

    

    

    

然后在我们的页面里面把这些imageView放到一个集合里面:

 private int[] resIds = {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 imageViews = new ArrayList<>();
  for (int resId : resIds) {
            ImageView imageView = findViewById(resId);
            imageView.setOnClickListener(this);
            imageViews.add(imageView);
        }

然后对iv_a这个设置一个点击事件,点一下展开menu,再点一下关闭menu。
一言不合上代码....
先说垂直展开菜单这个,设置Y轴偏移量根据i值变化,就可以程序上图那种萌萌哒的状态啦:

 private void openMenu() {
        for (int i = 1; i < resIds.length; i++) {
            ObjectAnimator animator = ObjectAnimator.ofFloat(imageViews.get(i), "translationY",
                    0F, i * 300F);
            animator.setDuration(500);
            animator.setInterpolator(new AccelerateInterpolator());
//            animator.setStartDelay(i*300);
            animator.start();
        }
        expand = true;
    }

关上!把这个菜单关上就是把所有的偏移量从现在的偏移量恢复成0:

   private void closeMenu() {
        for (int i = 1; i < resIds.length; i++) {
            ObjectAnimator animator = ObjectAnimator.ofFloat(imageViews.get(i), "translationY",
                    i * 300F, 0F);
            animator.setDuration(500);
            animator.setInterpolator(new AccelerateInterpolator());
//            animator.setStartDelay(i*300);
            animator.start();
        }
        expand = false;
    }

这里我解释一下 ObjectAnimator.ofFloat里面的几个参数,第一个参数是target,就是需要进行动画操作的目标,没错,就是这些imageView啦,第二个参数,需要改变的属性,没错,就是我们的Y轴偏移量TranslationY啦,后面的属性就是values,就是我们的属性值从哪个值变化到哪个值,可以清楚地看到展开菜单和关闭菜单的不同就是属性值的变化不同,展开是从0→i300,关闭时从i300→0。

setDuration就是动画从开始到结束这个时间长短。
setInterpolator就是动画的插值器,设置动画变化的规律,有9个默认的插值器,这里用的是默认的加速插值器AccelerateInterpolator,还有减速啊,回弹啊等等之类的,好的插值器链接参照:https://www.jianshu.com/p/88740cba25e6
一般插值器是为了让动画效果更接近现实,so,根据自身需要决定是否使用。

好,下一个,扇形展开菜单!

扇形的怎么展开呢?简单一看就是不仅有Y轴的偏移量还有X轴的偏移量!要让他呈扇形均匀展开,就是把扇形平均分成imageViews.size() - 1份,回顾一下数学:

弧度的定义:弧长等于圆半径长的弧所对的圆心角为1弧度,弧度没有单位。
即弧度=弧长/半径=l/r,因此,若弧度=π,弧长=πr=圆周的一半,此时恰好为一个半圆,圆心角180,也就是说π=180,1°=π/180

所以我们的角度计算公式为:

angle = (float) Math.PI / (2 * (imageViews.size() - 1));//(π/2)/(imageViews.size() - 1)

三角函数计算x轴y轴的偏移量:

 float x = (float) (r * Math.sin(i * angle));
 float y = (float) (r * Math.cos(i * angle));

不懂得同学请自己摸出草稿本画三角形
三角形的展开和收起动画:


    private void angleOpenMenu(float angle, float r) {
        for (int i = 1; i < resIds.length; i++) {
            float x = (float) (r * Math.sin(i * angle));
            float y = (float) (r * Math.cos(i * angle));
            PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", 0F, x);
            PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", 0F, y);
            ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageViews.get(i),
                    translationX, translationY);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.setDuration(500).start();
        }
        expand = true;
    }

    private void closeOpenMenu(float angle, float r) {
        for (int i = 1; i < resIds.length; i++) {
            float x = (float) (r * Math.sin(i * angle));
            float y = (float) (r * Math.cos(i * angle));
            PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", x, 0F);
            PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", y, 0F);
            ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageViews.get(i),
                    translationX, translationY);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.setDuration(500).start();
        }
        expand = false;
    }

细心的同学可以看到里面多了个PropertyValuesHolder,这个是用于组合多个动画,也可以像垂直展开动画一样单独写,如果需要定义动画顺序,比如先Y轴便宜再X轴偏移,或者Z轴和Y轴一起偏移,就需要使用AnimatorSet。

简单说一下AnimatorSet:

AnimatorSet.playTogether//动画一起播放;
AnimatorSet.playSequentially//动画按照顺序播放;
AnimatorSet.play(translationX).with(translationY)//动画X和Y一起播放;
AnimatorSet.play(translationY).after(translationX)//动画Y在动画X之后执行

好,到此结束。
有不对的地方请指正,O(∩_∩)O谢谢。

你可能感兴趣的:(menu展开动画(属性动画))