android 软软的动画弹出菜单,基于Facebook的Rebuond

6,573 阅读3分钟

 Hello,郭某又厚颜无耻的来码水文了,年终将至,又要被别人家程序猿的年终刷屏(年终奖和我有个Context关系(ノಠ益ಠ)ノ彡┻━┻)。所以,今天就让我们聊一点有意思♂的东西吧<( ̄ˇ ̄)/:“软软“的弹出菜单,一戳就破。没错,今天的片头就是这么短,此短非彼短,因为下面也很短。

 
︿( ̄︶ ̄)︿我是路过的DEMO : github.com/CarGuo/Anim…
 

等一下,我第二次弹出自带点击效果
 

rebound

 安利Facebook开源的弹簧动画库,模拟物理弹簧的效果,让直男♂的你从此软下来,产品经理再也不需要担心交互过硬了(✿◡‿◡)。

 rebound模拟的是物理效果,这里主要是有两个关键点:Tension(拉力系数)、Friction(摩擦系数)。Tension越大♀,弹性效果就越大,很符合逻辑是吧( ̄o ̄) ;Friction越大,受到的阻力就会越大,弹性效果就会降低。这里注意的是,弹性虽好,但摩擦力也是必须的哟,学过物理的你应该知道,没有摩擦力,根本停不下来啊,摩擦力太大,又进不···呸呸呸,又弹性不好。

 下方是facebook官方的demo,使用默认的F和T系数,创建一个Spring ,通过设置开始\接结束的系数,在监听过程中通过getCurrentValue,设置你想要的移动\放大\透明度等等效果,来实现你的动画,感觉是不是很ValueAnimation,简单易上手。

 有兴趣的可以去rebound下载官方demo,如果发现官方demo跑不来,可以试试我fork修改后的demo哟:github.com/CarGuo/rebo…

// Create a system to run the physics loop for a set of springs.
SpringSystem springSystem = SpringSystem.create();

// Add a spring to the system.
Spring spring = springSystem.createSpring();

// Add a listener to observe the motion of the spring.
spring.addListener(new SimpleSpringListener() {

  @Override
  public void onSpringUpdate(Spring spring) {
    // You can observe the updates in the spring
    // state by asking its current value in onSpringUpdate.
    float value = (float) spring.getCurrentValue();
    float scale = 1f - (value * 0.5f);
    myView.setScaleX(scale);
    myView.setScaleY(scale);
  }
});

// Set the spring in motion; moving from 0 to 1
spring.setEndValue(1);

实现动画弹出框

 
进入正题:

1、首先我们定义一个布局,包含四个圆形TAB,让它们呈现如下图效果。然后把它们都设置为GONE。

2、创建一个Spring用于执行动画。

  • 这里我们使用的是SpringChain,可以自定义我们想要的拉力和摩擦力系数,从左到右是主拉力,主摩擦力,辅助拉力,辅助摩擦力。
  • 根据TAB的个数,我们对每一个View通过springChain.addSpring添加到队列中,并设置对应的监听。
  • setCurrentValue设置初始化的开始数据为父布局的高度,这样每一个item就可以从屏幕底部开始弹出。
  • springChain.setControlSpringIndex(0).getControlSpring().setEndValue(0);设置起主导作用的是第一个tab,最后的终止数据是0,也就是原来所在的位置。
  • 在onSpringUpdate通过getCurrentValue换算出tab的位置和大小。

看下面,上面一堆废话,那个傻X说了那么多,哇塞,代码好简单啊(^o^)/,是不是觉得站在巨人的肩膀上,很自豪啊。收回动画就是把弹出的反过来即可,妥妥的。

SpringChain springChain = SpringChain.create(40, 6, 50, 7);

for (int i = 0; i < list.size(); i++) {

    final View view = list.get(i);

    springChain.addSpring(new SimpleSpringListener() {
        @Override
        public void onSpringActivate(Spring spring) {
            super.onSpringActivate(spring);
            view.setVisibility(VISIBLE);
        }

        @Override
        public void onSpringUpdate(Spring spring) {
            view.setTranslationY((float) spring.getCurrentValue());
            float scale = (1 + 2 * (float) spring.getCurrentValue() / mainView.getHeight());
            view.setScaleX(scale);
            view.setScaleY(scale);
        }
    });
}

List<Spring> springs = springChain.getAllSprings();

for (int i = 0; i < springs.size(); i++) {
    springs.get(i).setCurrentValue(mainView.getHeight());
}

springChain.setControlSpringIndex(0).getControlSpring().setEndValue(0);

 最后我们额外来个副菜,既然弹出\收起都有效果,那么“碰”起来也要有效果才对,这里我们就参考微博的菜单,在点击时候执行最后的动画效果。

 这个相对更加简单,我们使用系统的AnimationSet ,将点击的TAB放大和透明化动画一起执行,将其他的TAB同时缩小和透明化,动画结束时让tab隐藏起来,这样一个完整的菜单动画就结束啦。(。・・)ノ是不是好短啊,都说好短啦。

AnimationSet animationSet = new AnimationSet(true);
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f,
        Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);

animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);

animationSet.setInterpolator(new AccelerateInterpolator());
animationSet.setDuration(200);
animationSet.setFillAfter(false);

animationSet.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {
        view.setVisibility(GONE);
        ButtonClickLogin(view);

    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
});
view.startAnimation(animationSet);

最后说两句

 
两句。

瞅完了吧