热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android右上角动画,RecyclerView与LayoutAnimation实现的进入动画(二):Grid

介绍这是本教程的第二部分,也是最后一部分。第一部分我们讲述了RecyclerView用于列表的例子,文章见:在第一部分中我们演示了如何使用自定义的动画渲

介绍

这是本教程的第二部分,也是最后一部分。第一部分我们讲述了RecyclerView用于列表的例子,文章见:

在第一部分中我们演示了如何使用自定义的动画渲染一个RecyclerView的初始加载。采用的是LayoutAnimation,效果也不错。这篇文章我们谈谈如何用类似的方法去处理grid。

本教程的demo项目List和Grid的例子都有,在这里:

apk见 这里!

为什么grid场景下会有所不同?

首先采用第一部分中的方法完全可以在grid上很好的工作,没有crash,动画也是相同的运作方式。但是 LayoutAnimation与使用GridLayoutManager的RecyclerView得到的结果是这样的:

1503131496370933.gif

左边是LayoutAnimation的grid,右边是我们想要的效果。

之所以会这样是因为item的动画是基于它在grid中的线性位置来的(从左到右,从上到下),所以才会制造出奇怪的动画。我们想要的是不同列与行上的item同时运行,这样就能减短持续时间。概括起来就是我们需要对动画的顺序和延迟有更多的控制。

所以开始吧

为了解决这个问题,我们将使用GridLayoutAnimation。基本上它就是一个LayoutAnimation,但是可以为行与列定义delay,同时还允许设置 layout animation的方向。这就使得我们能更好的控制一个特定item的动画,更容易让多个item的动画同时运行。

首先在 res/anim/下创建一个名为grid_layout_animation_from_bottom.xml的文件,然后添加:

xmlns:android="http://schemas.android.com/apk/res/android"

android:animation="@anim/item_animation_from_bottom"

android:animationOrder="normal"

android:columnDelay="15%"

android:rowDelay="15%"

android:direction="top_to_bottom|left_to_right"

/>

其中:android:animation="@anim/item_animation_from_bottom”

定义布局中的每个item所要应用的动画

android:animationOrder="normal"

可以选择三种类型:normal, reverse 以及 random。它控制内容动画的顺序。Normal:遵循direction和delay所定义的顺序;Reverse的顺序恰好跟Normal相反;Random为随机的顺序。

android:columnDelay=”15%"

应用到每列上的动画延迟,定义为item动画持续时间的百分比。

android:rowDelay=”15%"

应用到每行上的动画延迟,定义为item动画持续时间的百分比。

android:direction=”top_to_bottom|left_to_right"

定义动画执行的方向。这里动画将从左上角开始,移动到右下角。如果定义为top_to_bottom|right_to_left,那么将从右上角开始移动到左下角。

对于一个GridLayoutAnimation来说,每个item最终的延迟是根据行和列的延迟以及方向计算出来的:itemAnimationDuration = 300ms

rowDelay              = 10% (30ms)

columnDelay           = 10% (30ms)

direction             = top_to_bottom|left_to_right

+------->

| +---+---+---+

| | 0 | 1 | 2 |

| +---+---+---+

V | 3 | 4 | 5 |

+---+---+---+

| 6 | 7 | 8 |

+---+---+---+    ROW   COLUMN

0 = 0*30 + 0*30 = 0ms

1 = 0*30 + 1*30 = 30ms

2 = 0*30 + 2*30 = 60ms3 = 1*30 + 0*30 = 30ms

4 = 1*30 + 1*30 = 60ms

5 = 1*30 + 2*30 = 90ms6 = 2*30 + 0*30 = 60ms

7 = 2*30 + 1*30 = 90ms

8 = 2*30 + 2*30 = 120msFinal animation order by delay

+-----+-----+-----+

|  0  | 30  | 60  |

+-----+-----+-----+

| 30  | 60  | 90  |

+-----+-----+-----+

| 60  | 90  | 120 |

+-----+-----+-----+

把行和列的延迟设置为相同值可以让item动画的执行是对称的(沿对角线)。第一部分的item动画 item_animation_from_bottom.xml是如此定义的:

android:duration="@integer/anim_duration_long">

android:interpolator="@android:anim/accelerate_decelerate_interpolator"

android:fromYDelta="50%p"

android:toYDelta="0"

/>

android:fromAlpha="0"

android:toAlpha="1"

android:interpolator="@android:anim/accelerate_decelerate_interpolator"

/>

应用 GridLayoutAnimation

GridLayoutAnimation的使用方式跟普通的LayoutAnimation是一样的,可以在java代码中也可以在xml中:

javaint resId = R.anim.grid_layout_animation_from_bottom;

LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(ctx, resId);

recyclerview.setLayoutAnimation(animation);

xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layoutAnimation="@anim/grid_layout_animation_from_bottom"

/>

但是如果你把GridLayoutAnimation用到标准的RecyclerView中会得到如下的异常:com.patrickiv.demo.enteranimationdemo E/AndroidRuntime: FATAL EXCEPTION: main

Process: com.patrickiv.demo.enteranimationdemo, PID: 19510

java.lang.ClassCastException: android.view.animation.LayoutAnimationController$AnimationParameters cannot be cast to android.view.animation.GridLayoutAnimationController$AnimationParameters

at android.view.animation.GridLayoutAnimationController.getDelayForView(GridLayoutAnimationController.java:299)

at android.view.animation.LayoutAnimationController.getAnimationForView(LayoutAnimationController.java:323)

at android.view.ViewGroup.bindLayoutAnimation(ViewGroup.java:4584)

at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3453)

at android.view.View.draw(View.java:17240)

at android.support.v7.widget.RecyclerView.draw(RecyclerView.java:3985)

...

这是因为RecyclerView是使用LayoutManager来布局自己的子view的,它并不知道LayoutManager如何放置子view。因此RecyclerView不知道到底该把AnimationParameter应用到list上还是grid上,而默认是list。为了修复这个问题我们需要一个自定义的RecyclerView,让它知道GridLayoutManager的存在。/**

* RecyclerView with support for grid animations.

*

* Based on:

* https://gist.github.com/Musenkishi/8df1ab549857756098ba

* Credit to Freddie (Musenkishi) Lust-Hed

*

* ...which in turn is based on the GridView implementation of attachLayoutParameters(...):

* https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/GridView.java

*

*/

public class GridRecyclerView extends RecyclerView {

/** @see View#View(Context) */

public GridRecyclerView(Context context) { super(context); }

/** @see View#View(Context, AttributeSet) */

public GridRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); }

/** @see View#View(Context, AttributeSet, int) */

public GridRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }

@Override

protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params,

int index, int count) {

final LayoutManager layoutManager = getLayoutManager();

if (getAdapter() != null && layoutManager instanceof GridLayoutManager){

GridLayoutAnimationController.AnimationParameters animationParams =

(GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;

if (animationParams == null) {

// If there are no animation parameters, create new once and attach them to

// the LayoutParams.

animationParams = new GridLayoutAnimationController.AnimationParameters();

params.layoutAnimationParameters = animationParams;

}

// Next we are updating the parameters

// Set the number of items in the RecyclerView and the index of this item

animationParams.count = count;

animationParams.index = index;

// Calculate the number of columns and rows in the grid

final int columns = ((GridLayoutManager) layoutManager).getSpanCount();

animationParams.columnsCount = columns;

animationParams.rowsCount = count / columns;

// Calculate the column/row position in the grid

final int invertedIndex = count - 1 - index;

animationParams.column = columns - 1 - (invertedIndex % columns);

animationParams.row = animationParams.rowsCount - 1 - invertedIndex / columns;

} else {

// Proceed as normal if using another type of LayoutManager

super.attachLayoutAnimationParameters(child, params, index, count);

}

}

}

现在唯一的事情就是在xml中把RecyclerView替换成新的GridRecyclerView:

android:id="@+id/recycler_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layoutAnimation="@anim/grid_layout_animation_from_bottom"

/>

结语

使用GridLayoutAnimation和自定义的GridRecyclerView,我们得到了想要的效果:

1503131496370933.gif

左边是LayoutAnimation的grid,右边是我们想要的效果。

代码地址。



推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 广度优先遍历(BFS)算法的概述、代码实现和应用
    本文介绍了广度优先遍历(BFS)算法的概述、邻接矩阵和邻接表的代码实现,并讨论了BFS在求解最短路径或最短步数问题上的应用。以LeetCode中的934.最短的桥为例,详细阐述了BFS的具体思路和代码实现。最后,推荐了一些相关的BFS算法题目供大家练习。 ... [详细]
  • 开发笔记:(002)spring容器中bean初始化销毁时执行的方法及其3种实现方式
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了(002)spring容器中bean初始化销毁时执行的方法及其3种实现方式相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文整理了Java中org.apache.pig.backend.executionengine.ExecException.<init>()方法的一些代码 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 我有一个带有H2数据库的springboot应用程序。该应用程序会在启动时引导数据库,为此,我在 ... [详细]
author-avatar
清清果冻儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有