对RecyclerView Item做动画

对RecyclerView Item做动画,刚刚开始研究的时候一些坑,在这里把一些设计思路分享出去

添加动态位移,静态位移,缩放等动画,保证了动画状态的平滑衔接

效果图:


我的Github,Demo下载

RecyclerView,ListView这些具有Item复用性的View,想要对其Item做动画,需要注意以下几点:

1,如果要一点击,让所有Item做动画的效果。例如,上图的编辑和取消,这样的动态动画。可以对所有ViewHolder中的View直接做动画。
但是需要在onBindViewHolder方法中对复用的item做静态动画,保证动画状态的平滑衔接。

2,每一个Item的特有属性,例如,上图checkbox的选中状态,都需要把状态字段放到对应的Java bean中, 并在onBindViewHolder方法从java bean取出状态值,设置到view里。

首先,对一些细节进行分析:

如何设计一个自定义View,来让他可以自己移动,做动画起来?

1,首先,创建一个View,他是RecyclerView Item的根布局:

public class SlideRelativeLayout extends RelativeLayout {public static final String TAG = SlideRelativeLayout.class.getSimpleName();private CheckBox mCheckBox;private RelativeLayout mContentSlide;private int mOffset;public SlideRelativeLayout(Context context) {super(context);}public SlideRelativeLayout(Context context, AttributeSet attrs) {super(context, attrs);}public SlideRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onFinishInflate() {super.onFinishInflate();mCheckBox = (CheckBox) findViewById(R.id.item_checkbox);mContentSlide = (RelativeLayout) findViewById(R.id.item_content_rl);setOffset(35);}public void setOffset(int offset) {mOffset = (int) (getContext().getResources().getDisplayMetrics().density * offset + 0.5f);}@TargetApi(Build.VERSION_CODES.HONEYCOMB)public void openAnimation() {ValueAnimator valueAnimator = new ValueAnimator();valueAnimator.setIntValues(0, 1);valueAnimator.setDuration(300);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float fraction = valueAnimator.getAnimatedFraction();int endX = (int) (-mOffset * fraction);doAnimationSet(endX, fraction);}});valueAnimator.start();}@TargetApi(Build.VERSION_CODES.HONEYCOMB)public void closeAnimation() {ValueAnimator valueAnimator = new ValueAnimator();valueAnimator.setIntValues(0, 1);valueAnimator.setDuration(150);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float fraction = valueAnimator.getAnimatedFraction();int endX = (int) (-mOffset * (1 - fraction));doAnimationSet(endX, (1 - fraction));}});valueAnimator.start();}@TargetApi(Build.VERSION_CODES.HONEYCOMB)private void doAnimationSet(int dx, float fraction) {mContentSlide.scrollTo(dx, 0);mCheckBox.setScaleX(fraction);mCheckBox.setScaleY(fraction);mCheckBox.setAlpha(fraction * 255);}public void open() {mContentSlide.scrollTo(-mOffset, 0);}public void close() {mContentSlide.scrollTo(0, 0);}}

这里,在View树创建完毕之后找到我们需要做动画的子View:

@Overrideprotected void onFinishInflate() {super.onFinishInflate();mCheckBox = (CheckBox) findViewById(R.id.item_checkbox);mContentSlide = (RelativeLayout) findViewById(R.id.item_content_rl);setOffset(35);}

然后,设计4个方法,分别为:动态的打开动画,动态的关闭动画,静态的打开动画,静态的关闭动画。

@TargetApi(Build.VERSION_CODES.HONEYCOMB)public void openAnimation() {ValueAnimator valueAnimator = new ValueAnimator();valueAnimator.setIntValues(0, 1);valueAnimator.setDuration(300);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float fraction = valueAnimator.getAnimatedFraction();int endX = (int) (-mOffset * fraction);doAnimationSet(endX, fraction);}});valueAnimator.start();}@TargetApi(Build.VERSION_CODES.HONEYCOMB)public void closeAnimation() {ValueAnimator valueAnimator = new ValueAnimator();valueAnimator.setIntValues(0, 1);valueAnimator.setDuration(150);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float fraction = valueAnimator.getAnimatedFraction();int endX = (int) (-mOffset * (1 - fraction));doAnimationSet(endX, (1 - fraction));}});valueAnimator.start();}@TargetApi(Build.VERSION_CODES.HONEYCOMB)private void doAnimationSet(int dx, float fraction) {mContentSlide.scrollTo(dx, 0);mCheckBox.setScaleX(fraction);mCheckBox.setScaleY(fraction);mCheckBox.setAlpha(fraction * 255);}public void open() {mContentSlide.scrollTo(-mOffset, 0);}public void close() {mContentSlide.scrollTo(0, 0);}@TargetApi(Build.VERSION_CODES.HONEYCOMB)private void doAnimationSet(int dx, float fraction) {mContentSlide.scrollTo(dx, 0);mCheckBox.setScaleX(fraction);mCheckBox.setScaleY(fraction);mCheckBox.setAlpha(fraction * 255);}

对子View做动画我采取的策略是:使用属性动画,在每一贞动画里获取到对应的值,对子View做相应的动画,例如:动态的打开动画。

onAnimationUpdate方法,显示每一贞动画都会回调一次

@TargetApi(Build.VERSION_CODES.HONEYCOMB)public void openAnimation() {ValueAnimator valueAnimator = new ValueAnimator();valueAnimator.setIntValues(0, 1);valueAnimator.setDuration(300);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float fraction = valueAnimator.getAnimatedFraction();int endX = (int) (-mOffset * fraction);doAnimationSet(endX, fraction);}});valueAnimator.start();}@TargetApi(Build.VERSION_CODES.HONEYCOMB)private void doAnimationSet(int dx, float fraction) {mContentSlide.scrollTo(dx, 0);mCheckBox.setScaleX(fraction);mCheckBox.setScaleY(fraction);mCheckBox.setAlpha(fraction * 255);}

这样RecylerView 带有动态动画和静态动画的View就设计好了。

2,在bind方法中使用静态动画,动态动画对外提供方法调用:

private class SlideViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {private SlideRelativeLayout mSlideRelativeLayout;private CheckBox mCheckBox;private ItemBean mItemBean;public SlideViewHolder(View itemView) {super(itemView);mSlideRelativeLayout = (SlideRelativeLayout) itemView.findViewById(R.id.item_root);mCheckBox = (CheckBox) itemView.findViewById(R.id.item_checkbox);itemView.setOnClickListener(this);}public void bind(ItemBean itemBean) {mItemBean = itemBean;mCheckBox.setChecked(itemBean.isChecked());switch (mState) {case NORMAL:mSlideRelativeLayout.close();break;case SLIDE:mSlideRelativeLayout.open();break;}}public void openItemAnimation() {mSlideRelativeLayout.openAnimation();}public void closeItemAnimation() {mSlideRelativeLayout.closeAnimation();}

可以看到静态动画在bind里调用,打开或者关闭是由mState变量决定的。而动态的滑动需要手动调用,那怎么来使用这些动画呢?

动态动画的使用方法:存储所有创建出来的ViewHolder,统一调用动态动画方法。并设置mState变量值,防止滑动时动画不能平滑衔接.

private List<SlideViewHolder> mSlideViewHolders = new ArrayList<>();public void openItemAnimation() {mState = SLIDE;//for (SlideViewHolder holder : mSlideViewHolders) {holder.openItemAnimation();}}public void closeItemAnimation() {mState = NORMAL;for (SlideViewHolder holder : mSlideViewHolders) {holder.closeItemAnimation();}}

而外面又是这样调用的:

private void editItems() {if ("编辑".equals(mRightTV.getText().toString())) {mRightTV.setText("取消");mSlideAdapter.openItemAnimation();} else if ("取消".equals(mRightTV.getText().toString())) {mRightTV.setText("编辑");mSlideAdapter.closeItemAnimation();}}

总体就是:点击按钮 – 变量ViewHolder集合做动态动画,并设置mState变量 – 手机滑动屏幕走bind方法又是根据mState做静态动画

动画从而平滑的衔接起来

再来看一次效果图:

动态动画起先,设置状态值,引导处理正确的静态动画,RecyclerView item的动画处理是不是变简单了。

还有,对item的特殊数据需要在对应的java bean里设置值,在bind方法取值设置到item中去。

分析就到这里了,小程序一枚。

我的Github

2016年7月01日 1:16:33

对RecyclerView Item做动画相关推荐

  1. recyclerview item动画_RecyclerView 的 Item 酷炫动画,效果加案例讲解!

    Caner Gures | 作者依然范特西稀 | 译者技术最TOP(ID:Tech-Android) | 来源 在完成 app 的编码之后,对于一个要求美观的现代 App 来说,仅仅实现功能是不够的, ...

  2. Android添加item动画,RecyclerView基础篇-Item添加动画

    Android_Banner.jpg 简介 本节中我们介绍下给RecyclerView中的Item添加动画. 添加的动画,分为,在打开列表时有Item的展示动画,当滑动的时候没有动画 和打开列表滑动时 ...

  3. recyclerview item动画_这可能是你见过的迄今为止最简单的RecyclerView Item加载动画...

    如何实现RecyclerView Item动画? 这个问题想必有很多人都会讲,我可以用ItemAnimator实现啊,这是RecyclerView官方定义的接口,专门扩展Item动画的,那我为什么要寻 ...

  4. android 资产管理动图,这可能是你见过的迄今为止最简单的RecyclerView Item加载动画...

    如何实现RecyclerView Item动画? 这个问题想必有很多人都会讲,我可以用ItemAnimator实现啊,这是RecyclerView官方定义的接口,专门扩展Item动画的,那我为什么要寻 ...

  5. RecycleView的Item Animator动画

    RecyclerView能够通过mRecyclerView.setItemAnimator(ItemAnimator animator)设置添加.删除.移动.改变的动画效果. RecyclerView ...

  6. RecyclerView零点突破(动画+边线篇)

    0.前言: 动画和边线估计有点冷门,很多人都将就凑合,今天我就来深入讲解一下吧 边线的方案是网上流传的一种,个人感觉也是最好的,并稍稍改进了一点 本篇使用的测试布局见上篇:RecyclerView零点 ...

  7. ListView底部item飞入动画效果

    最近有朋友展示了一种效果,就是ListView在滑动的过程中新加入的item会有一个从底部滑入的效果,我感觉这种效果还算不错,就去想了想拿到我身上应该怎么去实现这种效果,在试过几种方案后,最后选择了一 ...

  8. Android kotlin实现Recyclerview酷炫动画

    在现在进行app开发中 针对app的UI 美观效果要求越来越高了 所以开发出一款酷炫的app相当重要了 今天就对RecyclerView来实现酷炫动画 首先在Android studio中 的项目中 ...

  9. Android—ListView Item 展开动画效果

    Android-ListView Item 展开动画效果 最近在做一个关于ListView item的展开效果,类似于 "粮仓" App 的商店页面,点击Item,展开显示子Vie ...

最新文章

  1. SharePoint 2007图文开发教程(3)---实现简单的WebPart
  2. Linux下基本栈溢出攻击【转】
  3. 高性能 Windows Socket 组件 HP-Socket v2.3.1-beta-1 发布
  4. PAT甲级1119 Pre- and Post-order Traversals (30分):[C++题解]暴搜dfs、前序遍历和后序遍历求中序遍历
  5. 面试官问:能否模拟实现JS的new操作符(高频考点)
  6. 判断对象所有属性是否全部为空
  7. 吴恩达深度学习 —— 2.6 更多导数的例子
  8. 封装一个类似jquery的ajax方法
  9. JAVA解压Zip格式文件的代码
  10. 桌面虚拟化与带宽,延迟之间的关系
  11. mysql nutch,nutch结合mysql配置
  12. 达梦数据库dm8使用心得
  13. Samsung 6818平台首次编译遇到的问题
  14. 一、SQL语句执行过程
  15. 机器学习-吃瓜教程(西瓜书+南瓜书)-神经网络
  16. 07- Workbench网格划分概述
  17. Luogu 1315 【NOIP2011】观光公交 (贪心)
  18. Armadillo 线性代数库中的聚类算法避坑
  19. 584分学计算机报什么大学,高考成绩584分可以上哪些大学,2021年584分怎么填报志愿上什么大学...
  20. 自动驾驶行业观察之2023上海车展-----车企发展趋势(3)

热门文章

  1. Linux 命令(159)—— hostname 命令
  2. 一道经典的面试题:一只公鸡5块钱,一只母鸡3块钱,3只小鸡一块钱,一个农夫用100块钱买100只鸡(编写java程序)...
  3. 行列式在计算机的应用,行列式的计算机及应用.doc
  4. VC编程实现 excel插入一行单元格Insert
  5. 服务器mdf ldf文件,sqlserver2008如何导入mdf,ldf文件
  6. botzone Tetris2
  7. Could not autowire. No beans of ‘UserMapper‘ type found.
  8. android重力感应横竖屏,Android开发 apk强制横竖屏
  9. IGRP和EIGRP 详解
  10. 思科-实验10:路由器接口 PPP 协议封装和 PAP、CHAP 验证配置