Android中super.onBackPressed()与揭露动画的实现异常问题
问题分析与解决方案
你的问题根源在于Activity销毁时机和动画执行时机的冲突,具体来说:
- 原
onBackPressed()方法里同时调用了animateRevealClose()和super.onBackPressed(),这会导致揭露动画刚启动甚至还没启动时,Activity就开始执行销毁流程,后续按钮动画自然没机会展示。 - 就算在
animateRevealClose()的onAnimationEnd里调用了BottomFastSignUp(),但紧接着就调用RegisterActivity.super.onBackPressed(),会立即销毁当前Activity,按钮动画还没来得及执行就被中断了。
下面是具体的修复步骤:
第一步:修正onBackPressed()方法
先去掉onBackPressed()里的super.onBackPressed(),把返回的控制权完全交给自定义动画:
@Override public void onBackPressed() { // 只触发自定义关闭动画,不要直接调用默认返回逻辑 animateRevealClose(); }
第二步:调整动画结束后的逻辑
我们需要等底部按钮的显示动画完全执行完毕,再去销毁当前Activity,分两种情况处理:
情况1:可以修改BottomFastSignUp()返回动画对象
如果你的BottomFastSignUp()是通过属性动画实现的,修改它返回Animator对象,这样就能监听动画结束事件:
private Animator BottomFastSignUp() { // 示例:给登录按钮添加淡入+缩放的显示动画 View loginBtn = findViewById(R.id.btn_login); // 替换为你的按钮ID loginBtn.setAlpha(0f); loginBtn.setScaleX(0.8f); loginBtn.setScaleY(0.8f); loginBtn.setVisibility(View.VISIBLE); AnimatorSet animSet = new AnimatorSet(); animSet.playTogether( ObjectAnimator.ofFloat(loginBtn, View.ALPHA, 0f, 1f), ObjectAnimator.ofFloat(loginBtn, View.SCALE_X, 0.8f, 1f), ObjectAnimator.ofFloat(loginBtn, View.SCALE_Y, 0.8f, 1f) ); animSet.setDuration(300); // 动画时长可按需调整 return animSet; }
然后修改animateRevealClose()的动画监听器:
public void animateRevealClose() { int centerX = (mCardViewRegister.getWidth()) / 2; int centerY = (mToSignUpCardView.getTop() + mToSignUpCardView.getBottom()) / 2; int startRadius = mCardViewRegister.getHeight(); int endRadius = mToSignUpCardView.getWidth() / 2; Animator mAnimator = ViewAnimationUtils.createCircularReveal( mCardViewRegister, centerX, centerY, startRadius, endRadius); mAnimator.setDuration(500); mAnimator.setInterpolator(new AccelerateInterpolator()); mAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mCardViewRegister.setVisibility(View.INVISIBLE); // 获取底部按钮动画并启动,监听其结束事件 Animator bottomAnim = BottomFastSignUp(); bottomAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator anim) { // 按钮动画完全结束后,再执行返回逻辑 RegisterActivity.super.onBackPressed(); } }); bottomAnim.start(); } }); mAnimator.start(); }
情况2:无法修改BottomFastSignUp()的返回值
如果BottomFastSignUp()是直接设置View可见或用XML动画实现的,没办法返回Animator对象,可以用延迟的方式确保按钮动画执行完毕再关闭Activity:
public void animateRevealClose() { int centerX = (mCardViewRegister.getWidth()) / 2; int centerY = (mToSignUpCardView.getTop() + mToSignUpCardView.getBottom()) / 2; int startRadius = mCardViewRegister.getHeight(); int endRadius = mToSignUpCardView.getWidth() / 2; Animator mAnimator = ViewAnimationUtils.createCircularReveal( mCardViewRegister, centerX, centerY, startRadius, endRadius); mAnimator.setDuration(500); mAnimator.setInterpolator(new AccelerateInterpolator()); mAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mCardViewRegister.setVisibility(View.INVISIBLE); // 执行按钮显示动画 BottomFastSignUp(); // 延迟时间需和按钮动画时长一致 new Handler(Looper.getMainLooper()).postDelayed(() -> { RegisterActivity.super.onBackPressed(); }, 300); } }); mAnimator.start(); }
修复原理
我们把super.onBackPressed()的调用时机延后到了所有动画都执行完毕的时候,避免Activity提前销毁导致动画中断;同时修正onBackPressed()不再直接触发默认返回,确保自定义动画能完整执行。
内容的提问来源于stack exchange,提问作者Lyle
相关产品推荐
相关产品推荐

