这几天做了个带动画的分享页面,现在把它分享出来,如果你觉得有用,请直接使用,避免重复造轮子
觉得只是看效果图不明显,那么用手机扫描下面的二维码下载安装包:
这个效果本身没有什么特别的难度,都是用Animator实现的,只是动画效果的代码量有点多,因为分享模块一般都会做,把这个分享出来,想要用的话,就不要重复写这么多行代码了
对于熟悉Animator的人,下面的代码可以略过了
我来看下主要的实现代码,完整的代码看底部的项目Github地址
1. 我用了一个方法,实现进入的效果,加上判定,是否需要隐藏二维码页面
private void moveInAnim(boolean isHideCode) {
ObjectAnimator friendAnimatorX = ObjectAnimator.ofFloat(tvFriend, "TranslationX", 0);
ObjectAnimator friendAnimatorY = ObjectAnimator.ofFloat(tvFriend, "TranslationY", 0);
ObjectAnimator timelineAnimatorX = ObjectAnimator.ofFloat(tvTimeline, "TranslationX", 0);
ObjectAnimator timelineAnimatorY = ObjectAnimator.ofFloat(tvTimeline, "TranslationY", 0);
ObjectAnimator qrcodeAnimatorX = ObjectAnimator.ofFloat(tvQrcode, "TranslationX", 0);
ObjectAnimator qrcodeAnimatorY = ObjectAnimator.ofFloat(tvQrcode, "TranslationY", 0);
ObjectAnimator copyAnimatorX = ObjectAnimator.ofFloat(tvCopylink, "TranslationX", 0);
ObjectAnimator copyAnimatorY = ObjectAnimator.ofFloat(tvCopylink, "TranslationY", 0);
AnimatorSet set = new AnimatorSet();
set.setDuration(ANIM_TIME);
if (isHideCode) {
ObjectAnimator animatorX = ObjectAnimator.ofFloat(tvCode, "ScaleX", 0.1f);
ObjectAnimator animatorY = ObjectAnimator.ofFloat(tvCode, "ScaleY", 0.1f);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
tvCode.setVisibility(View.INVISIBLE);
}
});
set.playTogether(friendAnimatorX, friendAnimatorY, timelineAnimatorX, timelineAnimatorY
, qrcodeAnimatorX, qrcodeAnimatorY, copyAnimatorX, copyAnimatorY, animatorX, animatorY);
} else {
set.setInterpolator(new FastOutSlowInInterpolator());
set.playTogether(friendAnimatorX, friendAnimatorY, timelineAnimatorX, timelineAnimatorY
, qrcodeAnimatorX, qrcodeAnimatorY, copyAnimatorX, copyAnimatorY);
}
set.start();
}
在Animator中实现x轴跟Y轴,还有缩放的效果,有心人可能会发现,为什么我移动的参数都是0f呢,那么起始的值跑到哪里去了,请接着看第二点。
2. 初始化位置
tvFriend.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
tvFriend.getViewTreeObserver().removeOnPreDrawListener(this);
tvFriend.setTranslationX(-screenWidth / 2);
tvFriend.setTranslationY(-tvFriend.getHeight() * 2);
return false;
}
});
tvTimeline.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
tvTimeline.getViewTreeObserver().removeOnPreDrawListener(this);
tvTimeline.setTranslationX(screenWidth / 2);
tvTimeline.setTranslationY(-tvFriend.getHeight() * 2);
return false;
}
});
tvQrcode.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
tvQrcode.getViewTreeObserver().removeOnPreDrawListener(this);
tvQrcode.setTranslationX(-screenWidth / 2);
tvQrcode.setTranslationY(tvFriend.getHeight() * 2);
return false;
}
});
tvCopylink.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
tvCopylink.getViewTreeObserver().removeOnPreDrawListener(this);
tvCopylink.setTranslationX(screenWidth / 2);
tvCopylink.setTranslationY(tvFriend.getHeight() * 2);
return false;
}
});
初始化位置的方法,要放在addOnPreDrawListener中,这就是为什么在上一点中,只要把值设成0f就可以的原因
3. 移动出去的动画
private void moveOutAnim(boolean isFinishActivity, boolean isShowCode) {
ObjectAnimator friendAnimatorX = ObjectAnimator.ofFloat(tvFriend, "TranslationX", -screenWidth / 2);
ObjectAnimator friendAnimatorY = ObjectAnimator.ofFloat(tvFriend, "TranslationY", -tvFriend.getHeight() * 2);
ObjectAnimator timelineAnimatorX = ObjectAnimator.ofFloat(tvTimeline, "TranslationX", screenWidth / 2);
ObjectAnimator timelineAnimatorY = ObjectAnimator.ofFloat(tvTimeline, "TranslationY", -tvFriend.getHeight() * 2);
ObjectAnimator qrcodeAnimatorX = ObjectAnimator.ofFloat(tvQrcode, "TranslationX", -screenWidth / 2);
ObjectAnimator qrcodeAnimatorY = ObjectAnimator.ofFloat(tvQrcode, "TranslationY", tvFriend.getHeight() * 2);
ObjectAnimator copyAnimatorX = ObjectAnimator.ofFloat(tvCopylink, "TranslationX", screenWidth / 2);
ObjectAnimator copyAnimatorY = ObjectAnimator.ofFloat(tvCopylink, "TranslationY", tvFriend.getHeight() * 2);
AnimatorSet set = new AnimatorSet();
set.setDuration(ANIM_TIME);
if (isShowCode) {
addQrcode();
ObjectAnimator animatorScaleX = ObjectAnimator.ofFloat(tvCode, "ScaleX", 1f);
ObjectAnimator animatorScaleY = ObjectAnimator.ofFloat(tvCode, "ScaleY", 1f);
animatorScaleX.setInterpolator(overshootInterpolator);
animatorScaleY.setInterpolator(overshootInterpolator);
set.playTogether(friendAnimatorX, friendAnimatorY, timelineAnimatorX, timelineAnimatorY
, qrcodeAnimatorX, qrcodeAnimatorY, copyAnimatorX, copyAnimatorY, animatorScaleX, animatorScaleY);
} else {
set.playTogether(friendAnimatorX, friendAnimatorY, timelineAnimatorX, timelineAnimatorY
, qrcodeAnimatorX, qrcodeAnimatorY, copyAnimatorX, copyAnimatorY);
}
if (isFinishActivity) {
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
finish();
overridePendingTransition(0, 0);
}
});
}
set.start();
}
跟移动进来的动画大同小异,我就不复述了
4. 刚开始打开页面的时候,启动动画的方法:
tvFriend.post(new Runnable() {
@Override
public void run() {
moveInAnim(false);
}
});
用post的方法,可以很好的实现一开始的动画,如果直接在onResume中调用,或者其他的地方调用,就会出现卡顿,至于为什么这个方法可以,或者说有没有更好的的方法,希望有熟悉handle之类的人来解释下,感谢了
5. 注意的地方
有些手机会有默认的页面切换动画,比如我的M2手机就是向左滑动,退出就是向右滑动,为了避免有些手机的默认动画,可以在启动页面和退出页面的代码后面,加上如下的代码,避免出现默认的切换效果
overridePendingTransition(0, 0);
项目的源代码我放到了Github,欢迎查看!
有任何疑问或者探讨了,欢迎留言或者联系我