首页 > 系统 > Android > 正文

Android 转场动画+Adapter启动Activity

2019-11-08 00:33:22
字体:
来源:转载
供稿:网友

Android 转场动画+Adapter启动Activity

最近有个需求就是在RecyclerView中点击一个item然后跳出新的Activity,由于最近对于Material Design的翻译,所以也想做一个转场动画更为流畅的跳转。本文在环境 Android 5.0 及以上。

xiaoguo

本文参考: http://blog.csdn.net/wl9739/article/details/52833668

实现转场动画

在res/ 目录下创建 transition 文件夹,在该文件夹下定义界面转场动画和共享元素的动画。在 res/value/style 文件中为每个Activity指定转场动画的style, 并在 AndroidManifest.xml 文件中为每个 Activity 设置对应的 android:theme。在 Activity 调用 startActivity() 切换动画前,使用 ActivityOptionsCompat 来创建转场动画时的共享对象。

定义转场动画

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

Android 5.0(API 级别 21)支持这些进入与退出转换:

explode(分解): 从场景中心移入或移出视图slide(滑动): 从场景边缘移入或移出视图fade(淡入淡出): 通过调整透明度在场景中增添或移除视图

每一种动画效果,都有额外的属性。比如 slide,可以使用 android:slideEdge="top" 设置滑动的方向;fade 可以使用 android:fadingMode="fade_in" 设置具体是淡入还是淡出。

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

<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>

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

而我们想要在同一个过渡状态中实现两种或多种动画效果怎么办?也简单,将根标签替换为 <transitionSet/> ,然后定义每一种动画效果 。在根标签中可以使用 android:transitionOrdering 注明几种动画的演示顺序, sequential 表示顺序执行,而 together 表示同时执行。当然只有一个动画也可以使用该标签,这样以后要再加入动画,也很好修改,默认是同时执行所有动画。

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <fade> <targets> <target android:targetId="@id/article_date" /> <target android:targetId="@id/article_author" /> <target android:targetId="@id/article_title" /> <target android:targetId="@id/article_author_img" /> <target android:targetId="@id/article_spec" /> </targets> </fade> <slide android:slideEdge="bottom"> <targets> <target android:targetId="@id/article_content" /> </targets> </slide></transitionSet>

为每个 Activity 定义转场样式

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

界面A 跳转至 界面B:这时界面A是 exit(退出) 过渡状态,而对应的界面B是 enter(进入) 过渡状态。界面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>

上面的代码你会发现还有共享元素的动画效果,本文并没有涉及到共享元素的动画,读者可以自行查阅相关文章。

当然,你不必写全所有的属性,比如我在我的项目中定义的就是

<style name="AppTheme.Main" parent="IndexActivityTheme"> <item name="android:windowExitTransition">@transition/public_exit</item> </style>

定义了style,不要忘记要在 AndroidManifest.xml 文件中给相应的Activity 设置对应的 android:theme

<activity android:name=".Index" android:theme="@style/AppTheme.Main"> </activity>

调用 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());

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

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));

这里要注意的一点是,这里的view1,view2都必须是View类型的,所以你要使用例如TextView类型的view 的话,要强制转型为View,而”agreedName”就是在xml中 android:transitionName="agreedName" 定义的共享元素的名称。

一切本来都是这么顺利,但是问题出现了

Adapter启动Activity

RecyclerView中的点击事件,大家都应该熟悉了,我想实现的就是点击后跳转到新的Activity中,我的做法是在Adapter的onBindViewHolder中给view增加点击的监听事件。

但是问题来了,在 makeSceneTransitionAnimation 和 Intent的构造函数中都是需要 Activity 参数的,而在Adapter中如何才能获取到这一参数呢?这是一个问题。

我的解决方法是在Adapter中增加一个 Context 变量,并在onCreateViewHolder方法中给变量赋值,这样我们就能获取到上下文了。

PRivate Context mContext; @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mContext == null) { mContext = parent.getContext(); } ... }

这样的话,通过上下文我们就能获得Activity变量了,我们只要对Context变量进行强制类型转换成我们需要的那一个Activity类型即可,比如我的RecyclerView在Index这一个Activity中,我们来增加过场动画。

holder.mCardView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { new Handler().postDelayed(new Runnable() { @Override public void run() { ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation((Index) mContext, Pair.create((View) holder.articleImage, "image_transition")); Intent intent = new Intent(mContext, ArticleIndex.class); intent.putExtra("article", article); mContext.startActivity(intent, options.toBundle()); } }, 200); } });

在Intent的构造函数中,我们也可以直接将Context传入,会自动帮我们转化成Activity类型,这样的话,就大功告成了!


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表