Android RecyclerView 动画展开item显示详情
stackoverflow上看到这个问题,答主给了个demo
http://stackoverflow.com/questions/27446051/recyclerview-animate-item-resize
看懂了之后发个博,记录一下,刚开始看别人代码好难受,就这么3个文件看了一晚上。。
效果如下
res文件
main_activity文件就是一个recyclerview
main_item是两个textview 一个标题一个详细信息
MainActivity就是加载了一个RecyclerView
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
final RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(layoutManager);
final MainAdapter adapter = new MainAdapter();
rv.setAdapter(adapter);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
MainAdapter中new了一个keepOne对象,点进去看这个类,有两个方法:bind和toggle,其中的bind是在MainAdapter中的onBindViewHolder()方法中调用,而toggle是响应viewholder的点击事件
public static class KeepOneH<VH extends RecyclerView.ViewHolder & Expandable> {
// opened为-1表示所有item是关闭状态,open为pos值的表示pos位置的item为展开的状态
private int _opened = -1;
public void bind(VH holder, int pos) {
if (pos == _opened)
// 3
// 直接显示expandView 无动画
ExpandableViewHoldersUtil.openH(holder, holder.getExpandView(), false);
else
// 直接关闭expandView 无动画
ExpandableViewHoldersUtil.closeH(holder, holder.getExpandView(), false);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
@SuppressWarnings("unchecked")
// 响应点击事件的方法
public void toggle(VH holder) {
// 如果点击的就是开着的item,就关闭该item并把opened置-1
// ???TODO
if (_opened == holder.getPosition()) {
_opened = -1;
// 关闭expandView 有动画
ExpandableViewHoldersUtil.closeH(holder, holder.getExpandView(), true);
}
// 如果点击其他本来关闭着的item,则把opened值换成当前pos,把之前开的item给关掉
else {
int previous = _opened;
_opened = holder.getPosition();
// 展开expandView 有动画
ExpandableViewHoldersUtil.openH(holder, holder.getExpandView(), true);
// 用动画关闭之前的item
final VH oldHolder = (VH) ((RecyclerView) holder.itemView.getParent()).findViewHolderForPosition(previous);
if (oldHolder != null)
ExpandableViewHoldersUtil.closeH(oldHolder, oldHolder.getExpandView(), true);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
点进openH和closeH方法进去看
// 4
public static void openH(final RecyclerView.ViewHolder holder, final View expandView, final boolean animate) {
// animate参数为true,则有动画效果
if (animate) {
expandView.setVisibility(View.VISIBLE);
// 5
// 改变高度的动画,具体操作点进去看
final Animator animator = ViewHolderAnimator.ofItemViewHeight(holder);
// 扩展的动画结束后透明度动画开始
animator.addListener(new AnimatorListenerAdapter() {
@Override public void onAnimationEnd(Animator animation) {
final ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(expandView, View.ALPHA, 1);
alphaAnimator.addListener(new ViewHolderAnimator.ViewHolderAnimatorListener(holder));
alphaAnimator.start();
}
});
animator.start();
}
// animate参数为false,则直接设置为可见
else {
expandView.setVisibility(View.VISIBLE);
expandView.setAlpha(1);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
openH方法接收3个参数,
第一个是viewholder.
第二个是展开部分的view,由holder.getExpandView()方法获取。这里定义了一个接口
public static interface Expandable {
public View getExpandView();
}
- 1
- 2
- 3
- 1
- 2
- 3
在MainAdapter中传入infos这个Textview
@Override
public View getExpandView() {
return infos;
}
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
第三个是一个标记,true时有动画,false时直接设置其展开或者是关闭的状态。所以在bind()方法中调用的openH()都是false,而toggle()中调用的设置为true。
openH方法中 具体动画的操作为ViewHolderAnimator.ofItemViewHeight(holder)
public static Animator ofItemViewHeight(RecyclerView.ViewHolder holder) {
View parent = (View) holder.itemView.getParent();
if (parent == null)
throw new IllegalStateException("Cannot animate the layout of a view that has no parent");
// 测量扩展动画的起始高度和结束高度
int start = holder.itemView.getMeasuredHeight();
holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int end = holder.itemView.getMeasuredHeight();
// 6
final Animator animator = LayoutAnimator.ofHeight(holder.itemView, start, end);
// 设定该item在动画开始结束和取消时能否被recycle
animator.addListener(new ViewHolderAnimatorListener(holder));
// 设定结束时这个item的宽高
animator.addListener(new LayoutParamsAnimatorListener(holder.itemView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return animator;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
可以看出 具体展开的动画在LayoutAnimator.ofHeight(holder.itemView, start, end);中,ViewHolderAnimator只是测量参数,设定监听两个监听事件
1设定在动画开始结束和取消状态下是否可以被回收
public ViewHolderAnimatorListener(RecyclerView.ViewHolder holder) {
_holder = holder;
}
@Override
public void onAnimationStart(Animator animation) {
_holder.setIsRecyclable(false);
}
@Override
public void onAnimationEnd(Animator animation) {
_holder.setIsRecyclable(true);
}
@Override
public void onAnimationCancel(Animator animation) {
_holder.setIsRecyclable(true);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
2.设定在动画结束后view的高和宽分别为warp_content,match_parent.
public static class LayoutParamsAnimatorListener extends AnimatorListenerAdapter {
private final View _view;
private final int _paramsWidth;
private final int _paramsHeight;
public LayoutParamsAnimatorListener(View view, int paramsWidth, int paramsHeight) {
_view = view;
_paramsWidth = paramsWidth;
_paramsHeight = paramsHeight;
}
@Override
public void onAnimationEnd(Animator animation) {
final ViewGroup.LayoutParams params = _view.getLayoutParams();
params.width = _paramsWidth;
params.height = _paramsHeight;
_view.setLayoutParams(params);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
再深入一层看展开的动画
public class LayoutAnimator {
public static class LayoutHeightUpdateListener implements ValueAnimator.AnimatorUpdateListener {
private final View _view;
public LayoutHeightUpdateListener(View view) {
_view = view;
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final ViewGroup.LayoutParams lp = _view.getLayoutParams();
lp.height = (int) animation.getAnimatedValue();
_view.setLayoutParams(lp);
}
}
public static Animator ofHeight(View view, int start, int end) {
final ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new LayoutHeightUpdateListener(view));
return animator;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
是用ValueAnimator.ofInt生成一系列高度值,然后监听动画的变化,不断设定view的高度值
http://blog.csdn.net/gulumi_mmga/article/details/46683437
Android RecyclerView 动画展开item显示详情的更多相关文章
- Android解决RecyclerView中的item显示不全方案
最近的项目中实现订单确定页面.需要使用ScrollView嵌套RecyclerView,当RecyclerView中的item数量比较多时,就会出现item只显示一部分数据,并没有将用户勾选的商品数量 ...
- Android RecyclerView预览item
参考: Android Tools Attributes listItem 和 Sample Data 的用法 笔记 tools:text TextView可以实现预览,不影响实际的效果 例如: to ...
- Android Animation动画实战(一): 从布局动画引入ListView滑动时,每一Item项的显示动画
前言: 之前,我已经写了两篇博文,给大家介绍了Android的基础动画是如何实现的,如果还不清楚的,可以点击查看:Android Animation动画详解(一): 补间动画 及 Android An ...
- 解决ScrollView嵌套RecyclerView出现item显示不全的问题
问题:ScrollView嵌套RecyclerView时,RecyclerView的item显示不全 出现问题不要慌,耐心解决才是王道,哈哈.首先说下出现这个问题的情景吧,首先声明这个问题在23版 ...
- 【Android 界面效果49】RecyclerView高度随Item自适应
编写RecyclerView.ItemDecoration时,在onDraw方法中,Drawable的高度等于RecyclerView的高度减去RecyclerView的上下padding. @Ove ...
- Android 自定义View修炼-自定义可动画展开收缩View的实现
有时候需要点击一个view可以动画展开和收缩折叠一个View这样的效果,这样就可以直接自定义View来实现. 本例中,采用继承FrameLayout来实现自定义的ExpandView.下面将详细介绍各 ...
- Android窗口管理服务WindowManagerService显示窗口动画的原理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8611754 在前一文中,我们分析了Activi ...
- 基于css3的鼠标经过动画显示详情特效
之前为大家分享过一款基于jquery的手风琴显示详情,今天给大家分享基于css3的鼠标经过动画显示详情特效.这款实例鼠标经过的时候基于中间动画放大,效果非常不错,效果图如下: 在线预览 源码下载 ...
- Android RecyclerView 使用完全解析 体验艺术般的控件
概述 RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用. 据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我 ...
随机推荐
- [GitHub] GitHub Repositories
https://github.com/karqical2016/karqical2016.github.io.git https://github.com/karqical2016/java.git ...
- JavaScript学习08 Cookie对象
JavaScript学习08 Cookie对象 JavaScript Cookie Cookie对象: Cookie是一种以文件的形式保存在客户端硬盘的Cookies文件夹中的用户数据信息(Cooki ...
- 使用eclipse开发android准备工作
1.官网下载JDK http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html (注 ...
- 【即时通讯】即时通讯及XMPP概述及…
在讲解XMPP前,我们需要先了解什么是即时通讯技术: * 即时通讯技术(IM - InstantMessaging)支持用户在线实时交谈.当一方需要发送消息时,用户必须打开一个窗口,以便让用户与交流对 ...
- 数据持久化(一)--NSKeyedArchiver
数据持久化: 将内存中的数据按某种格式存进磁盘 数据的种类: 1,结构化的数据 2, 字节流数据 结构化的数据 字节流 内存中结构化的数据 -> 磁盘, 叫: 归档 字 ...
- igraph安装(R/Python)
python-igraph:啥都不说了,用Ubuntu吧,虽然按照官方的流程还是会出错,但是排错会比较少,一般找不了多久就能找到解决方案 R-igraph:一般需要升级R版本,用3.3吧.升级R的方法 ...
- 自定义底部工具栏及顶部工具栏和Fragment配合使用demo
首先简单的介绍下fragment,fragment是android3.0新增的概念,其中文意思是碎片,它与activity非常相似,用来在一个activity中描述一些行为或一部分用户界面.使用锁个f ...
- ADO.Net(一)——增、删、改、查
数据访问 对应命名空间:System.Data.SqlClient; SqlConnection:连接对象 SqlCommand:命令对象 SqlDataReader:读取器对象 CommandTex ...
- HDFS
1.HDFS shell 1.0查看帮助 hadoop fs -help <cmd> 1.1上传 hadoop fs -put <linux上文件> <hdfs上的路径& ...
- 【转】RHadoop实践系列之二:RHadoop安装与使用
RHadoop实践系列之二:RHadoop安装与使用 RHadoop实践系列文章,包含了R语言与Hadoop结合进行海量数据分析.Hadoop主要用来存储海量数据,R语言完成MapReduce 算法, ...