【问题标题】:Is transition animation not possible when using FLAG_ACTIVITY_CLEAR_TOP?使用 FLAG_ACTIVITY_CLEAR_TOP 时无法进行过渡动画吗?
【发布时间】:2015-03-26 09:38:47
【问题描述】:

我有一个MainActivity(它有launchMode=singleTop),我可以通过它进行其他活动,例如B 和C。现在,我想通过单击B 和C 中的某个按钮导航回MainActivity。我还想要过渡动画。

这是代码

CODE 1

Intent intent=new Intent(this,MainActivity.class);
        Bundle animation= ActivityOptions.makeCustomAnimation(getApplicationContext(), R.animator.translate_left_to_right, R.animator.translate_source_left_to_right).toBundle();
        startActivity(intent,animation);
        finish();

上面的代码工作正常,除了MainActivity 的新实例是在旧实例之上创建的!我不希望这种情况发生。因此,经过一番研究,我尝试了以下代码


CODE 2

Intent intent=new Intent(this,ListingActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        Bundle animation= ActivityOptions.makeCustomAnimation(getApplicationContext(), R.animator.translate_left_to_right, R.animator.translate_source_left_to_right).toBundle();
        startActivity(intent,animation);
        finish();

此代码似乎消除了创建活动新实例的问题,因为标志 FLAG_ACTIVITY_CLEAR_TOP 负责处理它。但是,现在过渡动画似乎不起作用!
标志FLAG_ACTIVITY_CLEAR_TOP 不允许任何动画吗?我的问题的解决方案是什么?我既需要动画过渡,也不需要创建 MainActivity 的新实例。


编辑
正如 David Wasser 所建议的那样,这似乎起到了作用。

 Intent intent=new Intent(this,ListingActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        finish();
        overridePendingTransition(R.animator.translate_left_to_right,R.animator.translate_source_left_to_right);

但是动画不流畅。动画中有一个小问题。我认为这是因为活动(B 或 C)在动画完成之前被破坏。我不确定

发布动画文件

translate_left_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="-100%p"
    android:toXDelta="0%p"
    android:duration="400"/>


translate_right_to_left.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100%p"
    android:toXDelta="0"
    android:duration="400"/>


translate_source_left_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0%p"
    android:toXDelta="50%p"
    android:duration="400"/>


translate_source_right_to_left.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="-50%p"
    android:duration="400"/>

【问题讨论】:

  • 尝试设置Intent.FLAG_ACTIVITY_SINGLE_TOP 和Intent.FLAG_ACTIVITY_CLEAR_TOP,看看是否有帮助。
  • 如果这不起作用,您可以在调用finish() 后尝试使用overridePendingTransition(int enterAnim, int exitAnim) 看看是否有帮助。
  • @DavidWasser :我通过将 MainActivity 设为“singleInstance”来使其工作。但问题仍然存在——CLEAR_TOP 怎么能让动画消失?
  • 恐怕使用单实例启动模式会给您带来比您预想的更多的麻烦。您的应用程序现在在 2 个单独的任务中运行。当您在顶部有活动 B 或 C 时,请尝试按 HOME 并查看最近的任务列表。这是一个非常糟糕的解决方案。
  • @DavidWasser hmmm.. 那么解决方案应该是什么。我尝试了您的第一个解决方案。这似乎行不通。将尝试覆盖并让您知道。

标签: android android-intent android-animation


【解决方案1】:

不使用Intent.FLAG_ACTIVITY_* 或另一个FLAG 有更好的解决方案。您可以尝试在AndroidManifest.xml 中添加android:noHistory="boolean" 属性。通过使用这个属性,请理解我下面的概念图​​:

说明

因为ActivityC和ActivityD(也和上次活动一起调用)有一个真实值,所以他们不能回MainActivity,但是可以先回ActivityA和ActivityB。此外,ActivityA 和ActivityB 可以返回MainActivity。因此,不会创建新实例。

在manifest中声明值后,只需要调用以下代码即可打开下一个Activity(不需要FLAG):

如果您想从C 或D 转到A(在这种情况下是您的活动,而不是概念图上的活动),请致电:

startActivity(new Intent(C.this, A.class));

再次查看概念图,ActivityA 与 ActivityC 链接,ActivityB 与 ActivityD 链接。因为这些活动看起来像链子,所以你不能直接调用finish()或按返回键去MainActivity。所以,调用上面的代码。

如果您想从ActivityB 转到您的ActivityA(在这种情况下是您的活动,而不是概念图上的活动),您可以致电finish()。默认情况下,Android 会在按下返回键时让你回到之前的活动,而无需调用finish()。

通常,我在使用android:noHistory="boolean" 属性时不需要android:launchMode 属性。

记住:

  • 在清单中将您的最后一个 Activity 设置为 android:noHistory="true"。
  • 另一个Activity 必须设置为 false 值。
  • 将此属性应用于您的所有活动。

另外,以下是如何在清单中使用它:

<activity android:name=".MyActivity" android:noHistory="true" />

添加动画

在您的ActivityA 中覆盖onResume() 方法(在这种情况下是您的活动,而不是概念图上的活动)并在此处制作动画:

@Override
public void onResume(){
    super.onResume();
    overridePendingTransition(R.anim.enterAnim, R.anim.exitAnim);
}

如果不适用于onResume() 方法,请尝试覆盖onStart() 方法中的动画:

@Override
public void onStart(){
    super.onStart();
    overridePendingTransition(R.anim.enterAnim, R.anim.exitAnim);
}

【讨论】:

  • 这根本没有解决 OP 的问题。 OP 在活动导航或工作流程方面没有问题。仅在特定情况下使用 Activity 过渡动画。无论如何,你的建议并不好。使用noHistory="true" 会产生各种副作用,这些副作用会扰乱应用程序的正常导航流程。看看如果您执行此操作,然后在屏幕上显示活动 A 或 B 时按下 HOME 按钮或接听来电,会发生什么情况。返回应用程序后,那些Activity就消失了!
  • noHistory 标志应谨慎使用,并且仅在您不希望用户能够返回到 Activity 的非常特定的情况下使用。
  • @DavidWasser,你是对的。我尝试按下使用noHistory="true" 设置活动的主页按钮。活动被破坏。
【解决方案2】:

我玩了很多次。我终于能够重现您的问题。我错过了MainActivity 的launchMode="singleTop",这就是为什么我之前没有看到这种行为。对此感到抱歉。

如果我在清单中将 launchMode="singleTop" 添加到 MainActivity,那么我可以使用代码 2 重现该行为。

使用我建议的代码,我能够解决问题:

    Intent intent=new Intent(this,ListingActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
    overridePendingTransition(R.animator.translate_left_to_right,
                              R.animator.translate_source_left_to_right);

不过,我还需要把动画资源文件translate_source_left_to_right.xml改成这样:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
       android:fromXDelta="0%p"
       android:toXDelta="100%p"
       android:duration="400" />

这就是导致动画中“故障”的原因。在同一时间段内,传入活动的动画从 -100% 变为 0%,传出活动的动画从 0% 变为 50%。所以传出的活动移动了屏幕宽度的一半,然后停止。我更改了传出动画,使其从 0% 变为 100%,现在您可以看到两个视图都在整个宽度上进行动画处理(我认为这是您想要的)。

感谢您的挑战:-)

【讨论】:

    【解决方案3】:

    我和你有同样的问题。
    但是,使用@David Wasser 的解决方案会在过渡期间牺牲视差效果。 可能有些开发者也不想要这样的行为。

    然后我通过检查您的 MainActivity 是否存在于 backstack 中来找到另一个解决方案。请在下面查看我的答案:

    how to check if activity is still in the stack?

    请注意,我的解决方案将使用系统的默认动画(与finish() 相同)禁用动画。但既然你真的要关闭当前的活动,我认为这更自然。

    【讨论】:

      【解决方案4】:

      发生这种情况是因为过渡没有开始过渡和结束过渡的对象当我们使用清除堆栈时,所有活动都会被清除,过渡将一无所有,因此通过在我的样式代码中实现以下行来做到这一点

      但是要谨慎使用这个

      &lt;item name="android:windowDisablePreview"&gt;true&lt;/item>

      【讨论】:

        猜你喜欢
        • 2011-03-31
        • 2020-07-25
        • 1970-01-01
        • 2023-03-26
        • 2018-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多