上一篇文章我们简单分析实现了Yalantis公司的SliderMenu,这次我们还是来写写它家的另一个动画
ContextMenu
github地址:https://github.com/Yalantis/Context-Menu.Android
效果如下
话不多说,同样我们来简单分析下
- 首先还是2个动画集合 :显示动画集合和隐藏动画集合
- 显示动画里面有2种动画,一种是第一个沿Y轴打开,第二种其他的沿X轴打开
- 隐藏动画里面比较特别,要观察仔细就可以发现里面有三种不同的动画,第一种前半部分是沿X轴向下收,第二种就是中间那个(也就是点击的那个)沿Y轴向里收,第三种下半部分是沿X轴向上收,和上半部分相反,还有一个重要的是上半部分和下半部分是同时播放 播放完后再执行中间那个
额 大家看明白了么 要多看几遍 仔细观察分析 复杂的动画其实都是由简单的动画组成的,不要被吓倒。
ok ,开始动手了,布局为了简单还是沿用上一篇文章的布局 如下
好的开始写各个不同的动画了
首先我们来写显示动画集合里面的2种动画
//Y show 打开-第一个
private ObjectAnimator createFlipYShowAnim(final View target) {
target.setPivotX(0);
target.setPivotY(target.getHeight() / 2);
ObjectAnimator invisToVis = ObjectAnimator.ofFloat(target, "rotationY", 90f, 0f);
invisToVis.setDuration(DURATION);
invisToVis.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
target.setVisibility(View.VISIBLE);
}
});
return invisToVis;
}
//x show 打开-下半部(第一个之外的)
private ObjectAnimator createFlipXShowAnim(final View target) {
target.setPivotX(target.getWidth() / 2);
target.setPivotY(0);
ObjectAnimator invisToVis = ObjectAnimator.ofFloat(target, "rotationX", -90f, 0f);
invisToVis.setDuration(DURATION);
invisToVis.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
target.setVisibility(View.VISIBLE);
}
});
return invisToVis;
}
再来写隐藏的三种动画
//x hidden before 隐藏-上半部
private ObjectAnimator createFlipXBeforeHiddenAnim(final View target, int i) {
target.setPivotX(target.getWidth() / 2);
target.setPivotY(target.getHeight());
ObjectAnimator visToInvis = ObjectAnimator.ofFloat(target, "rotationX", 0f, 90f);
if (i == 0) {
visToInvis.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
//播放完后恢复位置
target.setVisibility(View.INVISIBLE);
target.setPivotX(target.getWidth() / 2);
target.setPivotY(target.getHeight());
ObjectAnimator openAnim = ObjectAnimator.ofFloat(target, "rotationX", 90f, 0f);
openAnim.start();
}
});
}
visToInvis.setDuration(DURATION);
return visToInvis;
}
//Y hidden 隐藏-中间(点击部分)
private ObjectAnimator createFlipYHiddenAnim(final View target) {
target.setPivotX(0);
target.setPivotY(target.getHeight() / 2);
ObjectAnimator visToInvis = ObjectAnimator.ofFloat(target, "rotationY", 0f, 90f);
visToInvis.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
target.setVisibility(View.INVISIBLE);
target.setPivotX(0);
target.setPivotY(target.getHeight() / 2);
ObjectAnimator openAnim = ObjectAnimator.ofFloat(target, "rotationY", 90f, 0f);
openAnim.start();
}
});
visToInvis.setDuration(DURATION);
return visToInvis;
}
//x hidden after 隐藏-下半部
private ObjectAnimator createFlipXAfterHiddenAnim(View target) {
target.setPivotX(target.getWidth() / 2);
target.setPivotY(0);
ObjectAnimator visToInvis = ObjectAnimator.ofFloat(target, "rotationX", 0f, -90f);
visToInvis.setDuration(DURATION);
return visToInvis;
}
注释都加上了 没有什么特别的地方
现在我们开始把它们加到动画集合里面
显示动画集合
private AnimatorSet initShowAnim(ViewGroup parent) {
ArrayList<Animator> visAnimList = new ArrayList<Animator>();
for (int i = 0; i < parent.getChildCount(); i++) {
ObjectAnimator itemAnim = null;
if (i == 0) {//第一个动画
itemAnim = createFlipYShowAnim(parent.getChildAt(i));
} else {
itemAnim = createFlipXShowAnim(parent.getChildAt(i));
}
visAnimList.add(itemAnim);
}
AnimatorSet anim = new AnimatorSet();
anim.playSequentially(visAnimList);
return anim;
}
隐藏动画
隐藏动画稍微多点 因为它有多种动画 代码里面的MIDDLE我们假定为3 就是点击的哪个按钮位置
private Animator initHiddenAnim(ViewGroup parent) {
AnimatorSet beforAnim = new AnimatorSet();
AnimatorSet middleAnim = new AnimatorSet();
AnimatorSet afterAnim = new AnimatorSet();
ArrayList<Animator> beforeAnimList = new ArrayList<Animator>();
ArrayList<Animator> middleAnimList = new ArrayList<Animator>();
ArrayList<Animator> afterAnimList = new ArrayList<Animator>();
for (int i = 0; i < parent.getChildCount(); i++) {
if (i < MIDDLE) {
ObjectAnimator itemAnim = createFlipXBeforeHiddenAnim(parent.getChildAt(i), i);
beforeAnimList.add(itemAnim);
} else if (i > MIDDLE) {
ObjectAnimator itemAnim = createFlipXAfterHiddenAnim(parent.getChildAt(i));
afterAnimList.add(itemAnim);
} else {
ObjectAnimator itemAnim = createFlipYHiddenAnim(parent.getChildAt(i));
middleAnimList.add(itemAnim);
}
}
beforAnim.playSequentially(beforeAnimList);
middleAnim.playSequentially(middleAnimList);
Collections.reverse(afterAnimList);
afterAnim.playSequentially(afterAnimList);
AnimatorSet anim = new AnimatorSet();
anim.play(beforAnim).with(afterAnim).before(middleAnim);
return anim;
}
点击执行直接调用上面的方法了
initShowAnim(parent).start();//显示动画执行
initHiddenAnim(parent).start();//隐藏动画执行
为了理解简单 上面的代码并没有严格规范和优化,大家根据自己习惯自行调整了
ok 我们看一下最后的效果了 ( ps:录屏真是挺麻烦的 不知道有什么简单好用工具推荐)