转载

实现Activity间的共享控件转场动画

原文出处: http://www.jianshu.com/p/841f7b95ca77

Lollipop中有shared_element可以进行元素在activity之间进行共享,网上已经有很多介绍了,然而目前还有大量的kitkat设备,所以说啊,兼容更重要。

如下的方法,可以实现在旧的手机上实现动画效果。采用了类似于豌豆荚的开眼项目使用的技术.

实现Activity间的共享控件转场动画

Preview

实现原理

最近逛业界良心酷安网,发现了豌豆荚的一款叫做 开眼 的项目,这个项目的意义就是每天把墙外的东西搬运回来让村里的阿Q们开开眼,这款app至少目前看还没有那么毒瘤,还是比较小而美的,于是下载试用了一下。

有个转场动画使用了类似上面gif的效果,第一感觉是自定义了一个popwindow,于是起床,打开电脑,对两个效果的始末进行查询

# grep 是 unix命令,windows下先进shell再输入dump...内容 adb shell dumpsys window windows | grep -E 'mCurrentFocus'

结果如下,可以发现是2个activity,而不是自定义view实现的

mCurrentFocus=xx/com.wandoujia.eyepetizer.ui.activity.FeedActivity} mCurrentFocus=xx/com.wandoujia.eyepetizer.ui.activity.DetailActivity}

反复研究,最后发现原理如下

  1. FeedActivity将view的top/width/height,内容等信息通过intent进行发送

  2. DetailActivity设置为背景透明模式,转场动画关闭,这里关闭是非常重要的

  3. DetailActivity接着读取intent,并根据高度等信息进行动画绘制,由于DetailActivity的背景是透明的,所以用户会误认为是进行了“放大”操作

在UED中,“放大”与“右转”是两种常见的场景切换操作,安利一个叫做《Learn iOS Design》的书,Android开发者也值得借鉴一下

步骤

步骤非常简单,主要时间是耗在了调试动画上

1. 设置DetailActivity的主题

<style name="DetailedTheme" parent="AppTheme">   <!--背景透明-->   <item name="android:windowIsTranslucent">true</item>   <item name="android:windowBackground">@android:color/transparent</item>   <!--无进入动画-->   <item name="android:windowAnimationStyle">@null</item> </style>

2. 获取FeedActivity中的itemview

楼主在RecyclerView的Adapter中的viewholder中手动加了一个接口,在主界面实现

@Override public void onItemClick(View v, int position) {   Parcelable imgInfo = ((CardAdapter) mRecyclerView.getAdapter()).getData().get(position);   int top = v.getTop();   int heigh = v.getHeight();   int width = v.getWidth();   //发送Intent Extra   DetailedActivity.startActivity(v.getContext(), imgInfo, top, heigh, width); }

3. 在DetailActivity中进行动画

动画没有什么技巧,跟老司机开车一样,属于熟练工种,我们这里主要是使用了AnimationSet进行并发动画

void anim(View view, int top, int height, int width, boolean isEnter,     Animation.AnimationListener listener) {     //记住括号哦,我这里调试了一小时   float delta = ((float) width) / ((float) height);   float fromDelta, toDelta, fromY, toY;   if (isEnter) {     fromDelta = 1f;     toDelta = delta;     fromY = top;     toY = 0;   } else {     fromDelta = delta;     toDelta = 1f;     fromY = 0;     toY = top;   }   Animation anim = new ScaleAnimation(fromDelta, toDelta,       // Start and end values for the X axis scaling       fromDelta, toDelta, // Start and end values for the Y axis scaling       Animation.RELATIVE_TO_SELF, 0.5f, // scale from mid of x       Animation.RELATIVE_TO_SELF, 0f); // scale from start of y   Animation trans = new TranslateAnimation(0, 0f, fromY, toY);   AnimationSet set = new AnimationSet(true);   //添加并行动画   set.addAnimation(anim);   set.addAnimation(trans);   //动画结束后保持原样   set.setFillEnabled(true);   set.setFillAfter(true);   //监听器   set.setAnimationListener(listener);   set.setDuration(AnimateUtils.ANIM_DORITION);   view.startAnimation(set); }

这样,动画就搞定了,是不是很简单?

总结

源码仍在更新中,后期可能将加入大量仿iOS的组件

https://github.com/miao1007/Lollipop-Animation-Sample

最后,总结一下,这个东西实现不难,但是

  1. 调试动画太费时间了,暗坑多

  2. 大部分手机fps运行状态未知

  3. 编码改动量大,很难把所有业务封装在一个文件中,源码乱,后期维护困难

所以除了情怀,很少有专门的人愿意这样写,我建议在个人app中使用,或者提起商量好了再合作编码。另外关于状态栏适配,可以参考 这里

谢谢大家的观看,如果觉得本文有意义的话,不妨点个赞或者分享吧!

原文  http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0120/3897.html
正文到此结束
Loading...