受到iOS版的启发,在最近的项目中,我们决定在打开列表元素时实现一个类似风格的动画效果。起初,我们试图使用一个现有的实现——android-flip, 通过OpenGL渲染动画——在***的Android版本中,它只做到了在屏幕上显示比较明显的工件(图片闪烁)。另外,需要对这个类库进行改动,因为它 是为了滑动列表的元素设计的,但我们的工程需要在打开列表元素的时候有动画效果。在下面的演示视频中可以看出区别:android-flip实现的是折叠 列表,而我们实际需要的是展开详情。

考虑到这种场景,我们决定自己实现这种效果。因为应用程序支持的最小Android版本为4.0,所以没使用OpenGL,而是用了标准Android SDK中的方法:View.setRotationX(),View.setScaleX()等。当硬件加速启用时(如果目标API级别>=14,默认启用硬件加速),这些方法可以非常高效地利用GPU。

结果看起来很***,所以决定分享我们的做法。由于本文只是介绍了基本的实现要点,您可以从GitHub上下载所有的实际代码:FoldableLayout。

布局的实现

设计的***个元素是可以对折的布局。我们的做法相当大胆:主布局(FoldableItemLayout)只包含一个特定的布局(在baselayout)。在动画中,BaseLayout将它的内容写入到缓存中,这是一个根据原始布局的尺寸专门创建的Bitmap对象。

classFoldableItemLayoutextendsFrameLayout {

@Override

protectedvoidonSizeChanged(intw,inth,intoldw,intoldh) {

Bitmap cacheBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

mBaseLayout.setCacheCanvas(newCanvas(cacheBitmap));

}

}

classBaseLayoutextendsFrameLayout {

privateCanvas mCacheCanvas;

privatevoidsetCacheCanvas(Canvas cacheCanvas) {

mCacheCanvas = cacheCanvas;

}

@Override

publicvoiddraw(Canvas canvas) {

mCacheCanvas.drawColor(0, PorterDuff.Mode.CLEAR);

super.draw(mCacheCanvas);

}

}

此外,还需要两个额外的视图(PartView)——用于图像的上、下两半部分。它们将在缓存中显示对应的数据,这些数据代表了该图像(Bitmap)的上半部和下半部。两个视图填充了主布局的整个区域,但只显示所需的部分。为了达到这种效果,我们计算了位图的界限——在onDraw()方法中,我们让画布通过[drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)](http://developer.android.com/reference/android/graphics/Canvas.html#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint))方法来绘制所需的部分。

然后通过setRotationX()方法设置相应的角度,设法旋转这些额外的视图,从而实现图像上半部和下半部的独立旋转。为了实现这个功能,我们为FoldableItemLayout添加了一个名为FoldRotation的新参数。

FoldRotation参数范围是(-180,180]:

FoldRotation=0:两个部分都不旋转。在这种情况下,我们可以跳过位图缓存,实时的显示原始的布局。

0

-90

90≤FoldRotation<180:下层部分不再显示。在这种情况下,包含下一布局的FoldableItemLayout应该覆盖当前的FoldableItemLayout。

-180

FoldRotation=180:两个部分都隐藏。

现在有了一个二层布局,能够“折叠”它包含的元素,这样就可以做出一个FoldableListLayout——一个类似列表视图的布局,它创建列表元素,并通过使用BaseAdapter将其封装成FoldableItemLayout。在这种情况下,我们还使用了FoldRotation参数用来确定元素在列表中的位置。

例如,FoldRotation= 30,列表***个元素(FoldableItemLayout)的FoldRotation值为30,而第二个元素——FoldRotation= 150,最多可以同时显示不超过2个元素。FoldRotation参数值的范围依赖于元素的数量:如果列表包含一个元素,那么取值范围就会是 [0,0],2——[0,180],3——[0,360]等。

打开动画

在学会了在几个元素之间使用折叠动画滚动之后,我们解决了这个重大的挑战:从任意的起点生成元素的打开动画。利用已经实现的 FoldableListLayout, 并使其在两个元素之间进行切换:封面布局和详情布局。这两种元素都应该显示在屏幕上,但详情元素应该是隐藏的。当用户点击一个封面元素时,应用程序会记住 当时的位置,并使用相同大小的空占位符视图取代它(以免破坏屏幕上的其他元素),并移动盖元素的下半专门创建的布局。以后这种布局将被用作 FoldableListLayout的***个元素。第二个元素将被替换为空占位视图,与封面元素的方式相同。

对齐

眼见封面元素已经从屏幕上的最初位置展开,因此在动画过程中我们的FoldableListLayout需要在封面元素和详情元素的位置之间移动。这就是为什么要记住在动画初始化过程中每个元素的初始位置和大小的原因。由于封面和详情的大小有可能不同,我们需要在动画期间同时扩展它们,以便使它们的宽度一致。

我们基本已经完工,只差一件事:缩放后,封面的高度可能看起来比下半部分的详情小。这意味着你需要隐藏图像的剩余部分。

下面的屏幕截图显示了在动画的开始部分有一个灰色区域,下层的详情部分与封面的大小不符。

我们为FoldableItemLayoutm引入一个额外的RollingDistance参数解决了这个问题。这个参数负责从折线垂直移动图像。使用这个参数可以在动画的***部分中的不知不觉中转换详情的一部分,然后在第二部分中全尺寸展开。

动画现在就可以运行了,余下的工作就是为逼真的效果添加一些暗化,或为平滑的样子添加些阴影。本类库在GitHub上可以随意使用,在那里你还可以找到一个使用例子。一如既往的欢迎pull请求。

原文链接: azoft

【编辑推荐】

【责任编辑:闫佳明 TEL:(010)68476606】

点赞 0

android 折纸动画,如何在Android中实现折纸动画相关推荐

  1. android窗口退出动画,如何在Android中为弹出窗口制作动画

    PopupWindow自定义布局更方便,并且显示位置自由,没有任何限制.使用下面的代码并享受动画.在此动画中,使用底部滑入和滑出,但是您只能更改滑入/滑出动画,并根据您的动画对应用程序中的任何位置进行 ...

  2. android togglebutton 动画,如何在Android中使用ToggleButton多状态按钮控件

    如何在Android中使用ToggleButton多状态按钮控件 发布时间:2020-12-05 16:53:37 来源:亿速云 阅读:84 作者:Leah 这篇文章给大家介绍如何在Android中使 ...

  3. android led闪烁功能,如何在Android应用层中制作一个LED指示灯效果

    如何在Android应用层中制作一个LED指示灯效果 发布时间:2020-12-08 16:12:59 来源:亿速云 阅读:86 作者:Leah 本篇文章给大家分享的是有关如何在Android应用层中 ...

  4. android打电话的intent,如何在Android中使用intent打电话?

    如何在Android中使用intent打电话? 我正在使用以下代码在Android中进行调用,但它给了我安全例外,请帮忙. posted_by = "111-333-222-4"; ...

  5. android studio创建md,如何在Android Studio中设置*md文件打开方式

    最近在Android Studio中写一些Demo的时候,会顺便在里面创建一个.md文件用来进行Demo笔记的书写.然而Android Studio不带有markdown预览功能,所以我就琢磨如何在A ...

  6. Android清空Fragment缓存,如何在Android中清除Fragment Backstack

    如何在Android中清除Fragment Backstack 您好如何清除片段回堆栈正在使用以下逻辑,它不起作用... for(int i = 0; i < mFragmentManager. ...

  7. android指定日期闹钟,如何在android中设置特定日期的闹钟?

    嗨我需要使用时间选择器来设置特定日期的闹钟.当我给出静态输入时,闹钟设置不正确并响铃. 例如:我给静态输入(与日期,月份和年份),但它不振铃.这是我的代码.如何在android中设置特定日期的闹钟? ...

  8. android 调取数字键盘,如何在android中的EditText上显示数字键盘?

    如何在android中的EditText上显示数字键盘? 我只是想在某个EditText具有焦点时立即切换到数字键盘模式. 13个解决方案 239 votes 您可以为EditText配置EditTe ...

  9. unity editor android 黑屏_如何在Unity中利用nReal制作AR应用

    来源:新浪VR nReal眼镜是今年最有趣的增强现实小工具之一.它们已经在CES上展示过了,几个月前笔者在北京亲自试用过,在我的评测中,我强调了它们不仅非常轻.时尚,而且还能提供非常明亮的全息视图. ...

最新文章

  1. 数据库-ADONET-在数据集DataSet中使用关系对象DataRelation处理关系
  2. dedecms 备份和恢复的完整流程
  3. QTP、LoadRunner、QC工具下载地址
  4. ubuntu安装好后常用软件安装和配置
  5. linux配置文件为yum,yum的配置文件说明
  6. linux设备树例程,iTOP-iMX6-设备树内核-实时时钟RTC以及Linux-c测试例程
  7. windows制作docker镜像_.NET Core程序跑在任何有docker的地方
  8. C#之json序列化与反序列化
  9. android_get_control_socket 获取 UNIX 域套接字 FD
  10. Python求水仙花数
  11. HMC5883l磁力计数据读取
  12. Android支付宝刷步数,蚂蚁森林刷步数小技巧(一键修改支付宝步数)
  13. 计算机二级考试python考试大纲
  14. Color Banding的个人记录
  15. 备战面试日记(2.4) - (JVM.GC算法)
  16. Oracle EBS子库存转移,项目转移whole LPN
  17. VM虚拟机:VMware Kernel Module Updater
  18. MyBatis02:CRUD 操作
  19. python星星排列_python中怎么实现星星排列
  20. 十进制数与其他进制数转换方法及原理

热门文章

  1. 2022年危险化学品生产单位安全生产管理人员考题模拟考试平台操作
  2. 玩转apng实现动画效果
  3. 正则表达式匹配提取省市区
  4. 生活禅--铃木俊隆的12条生活准则
  5. Unity2D学习笔记-Tilemap
  6. 02-mysql多表查询
  7. 《浪潮之巅》与我的职业选择
  8. 优化小程序中频繁下拉刷新导致的定位获取失败问题
  9. Vue3 Element Plus 动态图标
  10. 华为云——代码托管的使用