Android中转场动画的实现与兼容性处理

Android中转场动画的实现与兼容性处理,第1张

概述前言在Android5.0之前,我们已经有了overridePendingTransition()方法来实现一些转场效果。然而,在Android5.0以后,转场效果更加炫酷。

前言

在 AndroID 5.0 之前,我们已经有了 overrIDePendingTransition() 方法来实现一些转场效果。然而,在 AndroID 5.0 以后,转场效果更加炫酷。

比如下面的动画

一、AndroID L 中的转场动画

实现转场动画只需三步:

       在 res/ 目录下创建 Transition 文件夹,在该文件夹下定义界面转场动画和共享元素的动画。

       在 res/value/style 文件中为每个 Activity 指定转场动画的 style ,并在 AndroIDManifest.xml 文件中为每个 Activity 设置对应的 androID:theme。

       在 Activity 调用 startActivity() 切换动画前,使用 ActivityOptionsCompat 来创建转场动画时的共享对象。
下面就来对这三步进行详细讲解。

二、定义转场动画

在 res/ 目录下创建了 Transition 资源文件夹后,就可以在该文件夹下对每一种动画进行定义。

一般来说,对 Activity 定义一个过渡动画可以写成下面的形式:

<explode xmlns:androID="http://schemas.androID.com/apk/res/androID"> <targets>  <target androID:excludeID="@androID:ID/statusbarBackground"/>  <target androID:excludeID="@androID:ID/navigationbarBackground"/> </targets></explode>

其中, 是动画效果的名称,AndroID 5.0(API 级别 21)支持这些进入与退出转换:

       1、分解(explode):从场景中心移入或移出视图。

       2、滑动(slIDe):从场景边缘移入或移出视图。

       3、淡入淡出(fade):通过调整透明度在场景中增添或移除视图。

而每一种动画效果,都有额外的属性。比如滑动 slIDe,可以使用 androID:slIDeEdge="top" 设置滑动的方向;淡入淡出(fade)可以使用 androID:fadingMode="fade_in" 设置具体是淡入(fade_in)还是淡出(fade_out)等。

标签里面定义需要转场(或者不需要转场)的目标 ID ,这个 ID 可以使系统自带的,也可以是我们自己视图中的 vIEw 的 ID,每一个 ID 需要单独在 标签中定义,androID:targetID 表示目标ID需要进行过渡转换的 vIEw,而 androID:excludeID 表示我们不需要该 ID 的 vIEw 进行过渡转场。上面的那段代码的意思是说,除了状态栏和导航栏以外所有的 vIEw,都执行 explode 动画。

如果我们想要在同一个过渡状态中实现两种或多种动画效果怎么办?也简单,将根标签替换为 ,然后定义每一种动画效果,最后记得在根标签中使用 androID:TransitionOrdering 注明这几种动画的演示顺序,sequential 表示顺序执行,而 together 表示同时执行。

比如像下面的代码:

<TransitionSet xmlns:androID="http://schemas.androID.com/apk/res/androID"> <slIDe androID:slIDeEdge="bottom">  <targets>   <target androID:targetID="@ID/cardvIEw"/>  </targets> </slIDe> <fade>  <targets>   <target androID:excludeID="@androID:ID/statusbarBackground"/>   <target androID:excludeID="@androID:ID/navigationbarBackground"/>   <target androID:excludeID="@ID/cardvIEw"/>  </targets> </fade></TransitionSet>

这段代码的意思就很简单了,该 xml 定义了两个过渡动画,并且同时执行。第一个动画是针对 ID 为 cardVIEw 的 vIEw 进行滑动,第二个动画将除了状态栏、导航栏和 cardvIEw 以外的 vIEw,进行淡入淡出。

三、为每个 Activity 定义转场样式

这里的每一种动画,指的是在进行界面跳转过渡时,两个界面的状态。比如对于 Activity A 和 Activity B 这两个界面,可能的状态如下:

       1、界面 A 跳转至界面 B :这时界面 A 是退出(exit )过渡状态,而对应的界面B是进入(enter)过渡状态。

       2、界面 B 返回到界面 A :这时界面 A 是重新进入(reenter)过渡,而对应的界面B则是返回(return)过渡。

一般来说,所有的 Activity 过渡动画都可以定义成如下的形式:

<style name="BaseApptheme" parent="androID:theme.Material"> <!-- 开启过渡效果 --> <item name="androID:windowContentTransitions">true</item> <!-- 指定界面进入/退出动画效果 --> <item name="androID:windowEnterTransition">@Transition/explode</item> <item name="androID:windowExitTransition">@Transition/explode</item> <!-- 指定共享元素进入/退出的动画效果 --> <item name="androID:windowsharedElementEnterTransition"> @Transition/change_image_transform</item> <item name="androID:windowsharedElementExitTransition"> @Transition/change_image_transform</item></style>

当然,你可以不用写全,比如在我的 Demo 中一个界面的转场动画文件如下:

<style name="Apptheme.Detail"> <item name="windowActionbar">false</item> <item name="androID:windowNoTitle">true</item> <item name="androID:windowTranslucentStatus">true</item> <item name="androID:windowAllowEnterTransitionOverlap">false</item> <item name="androID:windowEnterTransition">@Transition/detail_enter</item></style>

四、调用 ActivityOptionsCompat

转场动画是在两个界面的跳转返回时发生的,所以,当使用 intent 跳转界面时,需要调用 ActivityOptionsCompat来指定动画的运行。

一般来说,调用 ActivityOptionsCompat 的模板代码如下:

// 创建一个包含过渡动画信息的 ActivityOptions 对象ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,vIEw,getString(R.string.image_Transition_name));// 使用 Intent 跳转界面,并传递共享对象信息Intent intent = new Intent(this,DetailActivity.class);startActivity(intent,optionsCompat.toBundle());

ActivityOptionsCompat 是在support v4 包里面的,其实它是 ActivityOptions 的一个兼容(ActivityOptions是API 16引入的)。

然后,我们需要在第二个 Activity 中,将转场的图片获取并显示到界面中。

多个共享元素的过渡实现

有时候我们需要让多个元素产生动画效果,可以使用 Pair<> 来实现:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,Pair.create(vIEw1,"agreedname1"),Pair.create(vIEw2,"agreedname2"));

五、手动实现一个转场动画

现在市面上,AndroID 5.0 以下的手机系统还有一定的市场份额,所以为了照顾这些用户,我们只能手动实现一下共享元素的转场动画效果。

实现的思路也比较简单,大概的步骤如下:

        1、确定第一个界面的共享元素,将其信息传递个第二个界面

        2、第二个界面接收信息,开始的时候将界面设置为透明,并只显示共享元素。

        3、将第二个界面的共享元素进行动画处理。

那么我们开始一步步实现上面的步骤。

获取共享元素位置信息

在第一个界面中,我们需要获取到共享元素的位置信息,并将其传递给下一个界面。于是乎,我们可以在第一个界面元素点击事件中,这么写:

public voID imageClick(VIEw vIEw) { Intent intent = new Intent(AnimeActivity.this,AnimeDetailActivity.class); // 创建一个 rect 对象来存储共享元素位置信息 Rect rect = new Rect(); // 获取元素位置信息 vIEw.getGlobalVisibleRect(rect); // 将位置信息附加到 intent 上 intent.setSourceBounds(rect); CustomImage customImage = (CustomImage) vIEw; intent.putExtra(AnimeDetailActivity.EXTRA_IMAGE,customImage.getimageID()); startActivity(intent); // 屏蔽 Activity 默认转场效果 overrIDePendingTransition(0,0);}

其中,getGlobalVisibleRect() 方法的含义是,获取 可见的状态栏高度+可见的标题栏高度+Rect左上角到标题栏底部的距离,如果标题栏被隐藏了,那么可见标题栏高度为0。

接下来,就在在第二个界面接收位置信息并将该图片展示出来了。

模拟转场动画

在第二个界面中,我们需要做如下的 *** 作:

       1、获取上共享元素信息。

       2、计算共享元素缩放比例和位移距离。

       3、调用动画,完成模拟转场效果。

我将上面三个步骤的代码如下。

private voID initial() { // 获取上一个界面传入的信息 mRect = getIntent().getSourceBounds(); mRescourceID = getIntent().getExtras().getInt(EXTRA_IMAGE); // 获取上一个界面中,图片的宽度和高度 mOriginWIDth = mRect.right - mRect.left; mOriginHeight = mRect.bottom - mRect.top; // 设置 ImageVIEw 的位置,使其和上一个界面中图片的位置重合 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mOriginWIDth,mOriginHeight); params.setmargins(mRect.left,mRect.top - getStatusbarHeight(),mRect.right,mRect.bottom); mImageVIEw.setLayoutParams(params); // 设置 ImageVIEw 的图片和缩放类型 mImageVIEw.setimageResource(mRescourceID); mImageVIEw.setScaleType(ImageVIEw.ScaleType.CENTER_CROP); // 根据上一个界面传入的图片资源 ID,获取图片的 Bitmap 对象。 BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(mRescourceID); Bitmap bitmap = bitmapDrawable.getBitmap(); // 计算图片缩放比例和位移距离 getBundleInfo(bitmap); // 创建一个 Pallette 对象 mImagePalette = Palette.from(bitmap).generate(); // 使用 Palette 设置背景颜色 mContainer.setBackgroundcolor(   mImagePalette.getVibrantcolor(ContextCompat.getcolor(this,androID.R.color.black)));}

在12行,通过设置 margin 的形式来确定图片的位置,需要注意的是,由于状态栏是在父控件 FramLayout 之外的,因此我们要将 Rect.top 的值减去状态栏的高度,这样才是相对于屏幕的绝对位置。然后,getBundleInfo() 方法的代码如下:

private voID getBundleInfo(Bitmap bitmap) { // 计算图片缩放比例,并存储在 bundle 中 if (bitmap.getWIDth() >= bitmap.getHeight()) {  mScaleBundle.putfloat(SCALE_WIDTH,(float) mScreenWIDth / mOriginWIDth);  mScaleBundle.putfloat(SCALE_HEIGHT,(float) bitmap.getHeight() / mOriginHeight); } else {  mScaleBundle.putfloat(SCALE_WIDTH,(float) bitmap.getWIDth() / mOriginWIDth);  mScaleBundle.putfloat(SCALE_HEIGHT,(float) mScreenHeight / mOriginHeight); } // 计算位移距离,并将数据存储到 bundle 中 mTransitionBundle.putfloat(Transition_X,mScreenWIDth / 2 - (mRect.left + (mRect.right - mRect.left) / 2)); mTransitionBundle.putfloat(Transition_Y,mScreenHeight / 2 - (mRect.top + (mRect.bottom - mRect.top) / 2));}

动画处理

最后我们需要使用动画来模拟转场效果,代码如下:

private voID runEnteranim() { mImageVIEw.animate()    .setInterpolator(DEFAulT_INTERPolATOR)    .setDuration(DURATION)    .scaleX(mScaleBundle.getfloat(SCALE_WIDTH))    .scaleY(mScaleBundle.getfloat(SCALE_HEIGHT))    .translationX(mTransitionBundle.getfloat(Transition_X))    .translationY(mTransitionBundle.getfloat(Transition_Y))    .start();}

很简单,自此,入场动画效果基本模拟完毕。

而退场动画就更简单了,直接上代码:

private voID runExitAnim() { mImageVIEw.animate()    .setInterpolator(DEFAulT_INTERPolATOR)    .setDuration(DURATION)    .scaleX(1)    .scaleY(1)    .translationX(0)    .translationY(0)    .withEndAction(new Runnable() {     @OverrIDe     public voID run() {      finish();      overrIDePendingTransition(0,0);     }    })    .start();}

总结

以上就是AndroID中实现转场动画的全部内容,所以,是不是很简单?希望这篇文章的内容对各位AndroID开发者们能有所帮助,如果有疑问大家可以留言交流。

总结

以上是内存溢出为你收集整理的Android中转场动画的实现与兼容性处理全部内容,希望文章能够帮你解决Android中转场动画的实现与兼容性处理所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1147980.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存