如何在Android中的两个活动之间应用幻灯片动画?

76

我想要在从一个活动转移到另一个活动时实现从左到右的滑动效果。为此,我正在使用以下代码,但我没有得到任何结果。请帮我纠正。

在Java中的两个文件:

super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.fadein, R.anim.fadeout);
setContentView(R.layout.main);

res/anim目录下有两个文件:

fadein.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="5000"
    android:fromAlpha="0.0"
    android:interpolator="@android:anim/slide_out_right"
    android:toAlpha="1.0" >
</alpha>

淡出效果

<?xml version="1.0" encoding="utf-8"?>
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="5000"
    android:fromAlpha="0.0"
    android:interpolator="@android:anim/slide_in_left"
    android:toAlpha="1.0" >
</alpha>

我使用了这段代码:overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 您可以在GmailAnimationLopeAnimations中看到这些示例。此外,您还可以在Blog中查看更多内容。 - Cabezas
9个回答

177
将这两个文件添加到res/anim文件夹中。 R.anim.slide_out_bottom
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
    android:duration="@integer/time_duration_max"
    android:fromXDelta="0%"
    android:fromYDelta="100%"
    android:toXDelta="0%"
    android:toYDelta="0%" />
</set>

R.anim.slide_in_bottom

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
    android:duration="@integer/time_duration_max"
    android:fromXDelta="0%"
    android:fromYDelta="0%"
    android:toXDelta="0%"
    android:toYDelta="100%" /> 
</set>
在您的视图点击侦听器中写入下面的代码行。
startActivity(new Intent(MainActivity.this, NameOfTargetActivity.class));
overridePendingTransition(R.anim.slide_out_bottom, R.anim.slide_in_bottom);

15
谢谢 - 现在,当我按返回按钮回到旧的活动时,我应该把反向动画放在哪里? - Em Ae
3
@EmAe,我曾经问过一个类似的问题,并在这里自己回答了:https://dev59.com/hJvga4cB1Zd3GeqPwxpB#41025993。希望对你有帮助! - P Kuijpers
1
@Born To Win如果可以的话,您能否添加反向动画? - Amit Vaghela
这些动画不是反了吗?应该是(enterAnim,exitAnim)。 - hmac

140

在此输入图片描述

您可以覆盖默认的活动动画并使其比overridePendingTransition更好地执行。我使用这个解决方案,它适用于每个Android版本。只需复制粘贴4个文件并添加以下4行样式:

创建一个“CustomActivityAnimation”,并将其添加到您的基本主题中的“windowAnimationStyle”中。

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorPrimary</item>
    <item name="android:windowAnimationStyle">@style/CustomActivityAnimation</item>

</style>

<style name="CustomActivityAnimation" parent="@android:style/Animation.Activity">
    <item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item>
    <item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
    <item name="android:activityCloseEnterAnimation">@anim/slide_in_left</item>
    <item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
</style>

在res文件夹下创建anim文件夹,然后在anim文件夹中创建以下四个动画文件:

slide_in_right.xml

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="100%p" android:toXDelta="0"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>

slide_out_left.xml

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

slide_in_left.xml

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="-100%p" android:toXDelta="0"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>

向右滑出动画的XML文件

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0" android:toXDelta="100%p"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>

如果你遇到任何问题,那么你可以从我的github下载示例项目。

谢谢


1
我正在使用安卓6华为手机,它的表现非常出色。 :) - Shohan Ahmed Sijan
2
非常好,工作得非常好。我们不需要在所有意图中添加,这是这种方法的优势。谢谢Shohan。 - Manthan Patel
1
我喜欢这种解决方案!把它放在一个地方,无论在哪里都能完美运行! - vepzfe
2
这是一个神奇的解决方案,值得获得1000个赞。很少能找到像这样简单而优雅的解决方案。最重要的是,不需要丑陋的长代码,只需简单的XML即可完成所有操作。 - zeeshan
1
@AlessandroOrnano 不需要任何 Kotlin/Java 代码。只需从清单中提及应用程序主题即可。您可以查看示例 Github 项目。 - Shohan Ahmed Sijan
显示剩余8条评论

35
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splashscreen);

         new Handler().postDelayed(new Runnable() {
             public void run() {

                     /* Create an intent that will start the main activity. */
                     Intent mainIntent = new Intent(SplashScreen.this,
                             ConnectedActivity.class);
                     mainIntent.putExtra("id", "1");

                     //SplashScreen.this.startActivity(mainIntent);
                     startActivity(mainIntent);
                     /* Finish splash activity so user cant go back to it. */
                     SplashScreen.this.finish();

                     /* Apply our splash exit (fade out) and main
                        entry (fade in) animation transitions. */
                     overridePendingTransition(R.anim.mainfadein,R.anim.splashfadeout);
             }
     }, SPLASH_DISPLAY_TIME);   
    }

8
请不要执行这种延迟的Activity启动方式!即使您的应用程序不再处于前台,它也会启动您的MainActivity。 - Benoit

27

带有一些注意事项的alpha动画滑动

在这里输入图片描述

slide_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/activity_transition_time"
    >
    <translate
        android:fromYDelta="100%p"
        android:toYDelta="0"/>
    <alpha
        android:fromAlpha="0.5"
        android:toAlpha="1"/>
</set>

slide_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/activity_transition_time"
    >
    <translate
        android:fromYDelta="0"
        android:toYDelta="100%p"/>
    <alpha
        android:fromAlpha="1"
        android:toAlpha="0.5"/>
</set>

no_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/activity_transition_time"
    android:fromYDelta="0"
    android:toYDelta="0"/>

首个活动

startActivity(new Intent(this, SecondActivity.class));
overridePendingTransition(R.anim.slide_up,  R.anim.no_animation); // remember to put it after startActivity, if you put it to above, animation will not working
// document say if we don't want animation we can put 0. However, if we put 0 instead of R.anim.no_animation, the exist activity will become black when animate

第二个活动

finish();
overridePendingTransition(R.anim.no_animation, R.anim.slide_down);

完成

更多
我试图让滑动动画像iOS动画一样在呈现视图模型时(像这个https://www.youtube.com/watch?v=deZobvh2064),但失败了。

看看iOS的present动画,你会发现:从底部有一个透明度(大约50%)的动画,然后它快速地转换为更慢的动画,动画时间大约> 500ms(我使用trim video工具来计算动画时间https://www.kapwing.com/trim-video所以无法确切到达100%)

然后我尝试应用到Android。
为了使alpha,我使用<alpha>并成功。
为了使动画开始比较快,然后变慢,我使用了android:interpolator="a decelerate interpolator"但几乎失败了。

Android有3个默认的decelerate interpolator
@android:interpolator/decelerate_quad -> 因子=1
@android:interpolator/decelerate_cubic -> 因子=1.5
@android:interpolator/decelerate_quint _> 因子=2.5
(较高的因子<=>动画从开始时启动更快,结束时变得更慢)
这是一个很好的教程http://cogitolearning.co.uk/2013/10/android-animations-tutorial-5-more-on-interpolators/来理解它

我尝试了上面的3个插值器,但无法像iOS那样实现,动画无法像iOS那样更快地启动。然后我创建了一个自定义的decelerateInterpolator,因子为3,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:factor="3" />

我将持续时间从500 -> 750增加。它表现良好(与 iOS 非常相似)。但是,在某些设备上,它只能正常运行,而在一些设备上,动画速度相当慢。后来,我知道不同的设备可能有不同的动画效果(例如:某些设备会更快,而某些设备会更慢),因此我无法使所有 Android 设备中的动画效果相似。因此,我不使用interpolator。我不知道我的测试是否完全准确,但我希望这个经验能够有所帮助。


4

希望这对您有用。

startActivityForResult( intent, 1 , ActivityOptions.makeCustomAnimation(getActivity(),R.anim.slide_out_bottom,R.anim.slide_in_bottom).toBundle());

4

这里有一个幻灯片动画。

enter image description here

假设您有两个活动:

  1. MovieDetailActivity
  2. AllCastActivity

当单击按钮时,会发生以下情况。

enter image description here

您可以通过以下3个简单步骤实现此目标

1)启用内容转换

进入style.xml并添加以下行以启用内容转换。

<item name="android:windowContentTransitions">true</item>

2) 为您的AllCastActivity编写默认的进入和退出过渡效果

public void setAnimation()
{
    if(Build.VERSION.SDK_INT>20) {
        Slide slide = new Slide();
        slide.setSlideEdge(Gravity.LEFT);
        slide.setDuration(400);
        slide.setInterpolator(new AccelerateDecelerateInterpolator());
        getWindow().setExitTransition(slide);
        getWindow().setEnterTransition(slide);
    }
}

3) 使用Intent启动Activity

将此方法编写到您的MovieDetailActivity中,以启动AllCastActivity

public void startActivity(){

Intent i = new Intent(FirstActivity.this, SecondActivity.class);
i.putStringArrayListExtra(MOVIE_LIST, movie.getImages());

  if(Build.VERSION.SDK_INT>20)
   {
       ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(BlankActivity.this);
       startActivity(i,options.toBundle());
   }
   else {
       startActivity(i);
   }
}

最重要的事情!

setContentView()方法之前放置你的setAnimation()方法,否则动画将无法正常工作。
因此,你的AllCastActivity.java应该像这样:

 class AllCastActivity extends AppcompatActivity {

   @Override
   protected void onCreate(Bundle savedInstaceState)
   {
      super.onCreate(savedInstaceState);

      setAnimation();

      setContentView(R.layout.all_cast_activity);

      .......
   }

   private void setAnimation(){

      if(Build.VERSION.SDK_INT>20) {
      Slide slide = new Slide();
      slide.setSlideEdge(Gravity.LEFT);
      ..........
  }
}

3

Kotlin例子:

    private val SPLASH_DELAY: Long = 1000

    internal val mRunnable: Runnable = Runnable {
        if (!isFinishing) {
            val intent = Intent(applicationContext, HomeActivity::class.java)
            startActivity(intent)
            overridePendingTransition(R.anim.slide_in, R.anim.slide_out);
            finish()
        }
    }


   private fun navigateToHomeScreen() {
        //Initialize the Handler
        mDelayHandler = Handler()

        //Navigate with delay
        mDelayHandler!!.postDelayed(mRunnable, SPLASH_DELAY)

    }

    public override fun onDestroy() {

        if (mDelayHandler != null) {
            mDelayHandler!!.removeCallbacks(mRunnable)
        }

        super.onDestroy()
    }

将动画放在anim文件夹中: slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<translate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="@android:integer/config_longAnimTime"
        android:fromXDelta="100%p"
        android:toXDelta="0%p">
</translate>

slide_out.xml

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

使用方法

  navigateToHomeScreen();

0

通过调用overridePendingTransition并传递进入活动和退出活动的动画资源,可以将幻灯片动画应用于活动转换。

幻灯片动画可以向右滑动,向左滑动,向上滑动和向下滑动。

向上滑动

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator">
    <scale
        android:duration="800"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:toXScale="1.0"
        android:toYScale="0.0" />
</set>

下滑

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator">
    <scale
        android:duration="800"
        android:fromXScale="1.0"
        android:fromYScale="0.0"
        android:toXScale="1.0"
        android:toYScale="1.0" />
</set>

overridePendingTransition(R.anim.slide_down, R.anim.slide_up);

更多活动转换示例参见 activity transition animation examples


0

你可以在 startActivity 中使用 overridePendingTransition,而不是在 onCreate 中使用。至少,在我这里是有效的!

在这里可以看到一个完整的例子here。它包括了在返回到上一个活动时进行 (反向) 动画 onBackPressed!在您特定的例子中(淡入和淡出),这可能是不必要的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接