Actvitiy跳转动画(一)
上一篇介绍了基本的跳转动画,包括平移、旋转、组合效果等。今天来讲一下更炫酷的效果——5.0转场动画。
转场动画分为四种,分别是Explode、Slide、Fade,和Share
项目源码地址 https://github.com/TaciturnKnight/AndroidAnimatorDemo
Explode
这个效果是页面内的控件从四面八方飞入屏幕,最后组成页面,先来看下效果
explode.gif
实现这个效果只需要两步
第一步:在startActivity时传递一个Bundle参数
var intent: Intent = Intent(mContext, ExplodeActivity::class.java)
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this@AnimActivity).toBundle())
第二步:在新启动的activity中调用setEnterTransition
kotlin代码
window.enterTransition = Explode()
java代码:
getWindow().setEnterTransition(new Explode());
Slide
slide效果是页面内的控件以不同的先后顺序滑入屏幕
slide.gif
代码实现和explode相同,只不过在设置enterTransation时多传了一个参数,代表滑动的方向
window.enterTransition = Slide(Gravity.TOP)
Fade
fade效果和我们上一篇介绍过的淡入淡出的效果一样,页面从完全透明变为不透明
代码实现和explode相同,传一个Fade对象就可以了
window.enterTransition = Fade()
Share
下面重点介绍一下share,先看下效果
share.gif
这个效果在列表跳转详情页时比较常见,比如最近刚复活的TapTap,在被封了下载三个月之后,不但没有一蹶不振,反而把自己的产品非常细致地打磨了一遍,跟之前相比优化了好多细节。置之死地而后生,这种力量确实让我感到很震撼
又跑题了,接着说我们的share动画
仔细看上面的效果,页面A跳转到页面B,给人感觉没有跳转一个新的页面,而是在A页面把信息放大展示。那这个效果是怎么实现的呢
其实是在启动activity的时候,先记录要共享的控件在当前屏幕的位置和大小,跳转之后,新的activity对应的控件从刚才的位置平移到当前页面的位置,同时大小从上一个页面的大小放大为当前页面的大小,执行了这样一个动画。
当然,系统已经封装好了这个动画,那我们怎么去使用呢
第一步:指定页面A中要共享的控件
第二步:指定页面B中要共享的控件
对,就是这么简单,下面上代码
页面A中:
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this@ShareAnimListActivity
, Pair.create(view, "sharename")).toBundle())
其中,Pair.create方法中,第一个参数指定页面A中要共享的控件,第二个参数传一个标识,自定义的字符串,我们暂且叫他shareName
需要注意的是
makeSceneTransitionAnimation(Activity activity, Pair<View, String>... sharedElements)
这个方法的sharedElements参数,是一个可变参数,也就是说,我们可以传递多个Pair.create(),这样可以实现两个页面共享多个参数。
页面B中:
只需要在要共享的控件上加一个属性
android:transitionName="sharename"
值就是我们在页面A中指定的shareName
然后在onCreate里加一句
kotlin:
window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
java:
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
这句话要在setContentView之前调用,代表启用Transation过渡动画。关于Transation动画这里不做过多介绍,有机会会在后边的帖子里专门介绍Transation动画
至此我们就可以实现share动画了。
扩展
怎样从列表中获取到某一个条目中的某个控件
在这个例子里我用的是RecylcerView。我们知道RecyclerView是有LayoutManager的,通过这个LayoutManager我们就可以获取到每个条目的子控件
var layoutManager: RecyclerView.LayoutManager = recyclerView.layoutManager
var view: View = layoutManager.findViewByPosition(position)
var holder: TestRecyclerAdapter.Holder = recyclerView.getChildViewHolder(view) as TestRecyclerAdapter.Holder
java代码就不贴了,其实就是LayoutManager的findViewByPosition方法获取到当前条目的View,然后可以直接用这个view.findViewById,也可以用recyclerView的getChildViewHolder获取到这个view的holder,拿到holder之后,就什么都有啦。
RecylcerView还有个方法叫public View getChildAt(int index)
为什么不用这个方法呢?因为这个方法的index,代表的是当前屏幕内的index。举个例子,一个列表有50个条目。在没有滑动的情况下getChildAt(0)返回的是第一个条目。如果当前屏幕能容纳6个条目,那当我们滑动到当前屏幕显示的是第10——第16个条目时,getChildAt(0)返回的就是第10个条目。
也就是说getChildAt方法中的index参数,代表的是当前屏幕中的index,而不是真正的position。而LayoutManager的findViewByPosition方法,可以根据当前点击的position,去获取到对应的view。
这个方法也可以做列表的局部刷新用,也就是当列表的某一条数据改变时,可以不全部刷新,而只刷新单独的一个条目,从而提高执行效率
完整代码:
var layoutManager: RecyclerView.LayoutManager = recyclerView.layoutManager
var view: View = layoutManager.findViewByPosition(position)
var holder: TestRecyclerAdapter.Holder = recyclerView.getChildViewHolder(view) as TestRecyclerAdapter.Holder
var intent: Intent = Intent(mContext, ExplodeActivity::class.java)
intent.putExtra(AnimatorConstants.INTENT_TAG, AnimatorConstants.SHARE)
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this@ShareAnimListActivity
, Pair.create(holder.title, "sharetitle")
, Pair.create(holder.desc, "sharedesc")
, Pair.create(holder.pic, "sharepic")).toBundle())
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher_round"
android:transitionName="sharepic" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:transitionName="sharedesc" />
<TextView
android:id="@+id/detail_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:transitionName="sharetitle" />
项目源码地址 https://github.com/TaciturnKnight/AndroidAnimatorDemo
以上就是Activity转场动画,喜欢的朋友点点关注
欢迎大神指出缺陷和不足,互相学习,共同进步
网友评论