您的位置:首页 > 移动开发 > Android开发

Android 转场动画+Adapter启动Activity

2017-02-23 22:26 525 查看

Android 转场动画+Adapter启动Activity

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



本文参考:

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

转场动画是在两个界面的跳转返回时发
b03b
生的,所以,当使用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类型,这样的话,就大功告成了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android
相关文章推荐