ListView弹性下拉效果
2015-12-20 13:31
337 查看
开源项目地址:https://github.com/chiemy/PullSeparateListView
效果图:
用什么实现的?
通过属性动画和事件分发机制实现的。
只分析实现原理和关键代码:
1.自定义一个View继承ListView
2.复写ListView的dispatchTouchEvent方法
3.在dispatchTouchEvent的MotionEvent.ACTION_MOVE事件中检测有没有滑动到最顶部和最底部,如果滑动到最底部则执行上拉的弹性效果。如果滑动到最顶部则实现下拉的弹性效果。
4.弹性效果的实现,for循环遍历每一个Item,根据每个item的索引(position),计算每一个item在Y方向上的偏移量,在每个item的Y方向执行属性动画。
5.松开手指,恢复到原来的状态,实现原理:遍历每一个Item实现,将每一个Y方向上的偏移量(offsetY)置为0,通过属性动画将状态复原。
效果图:
用什么实现的?
通过属性动画和事件分发机制实现的。
只分析实现原理和关键代码:
1.自定义一个View继承ListView
public class PullSeparateListView extends ListView { }
2.复写ListView的dispatchTouchEvent方法
// 核心代码 @Override public boolean dispatchTouchEvent(MotionEvent ev) { float currentY = ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: float downX = ev.getX(); float downY = ev.getY(); // 记录按下位置,当isSeparateAll()返回false时,会用到 originDownPosition = pointToPosition((int) downX, (int) downY); downPosition = originDownPosition - getFirstVisiblePosition(); if (showDownAnim) { performDownAnim(downPosition); } break; case MotionEvent.ACTION_MOVE: // 记录到达顶部或底部时手指的位置 if (!separate) { startY = currentY; } deltaY = currentY - startY; // 到达顶部 if (reachTop) { if (!separateFromTop(currentY)) { return super.dispatchTouchEvent(ev); } return false; } // 到达底部 if (reachBottom) { if (!separateFromBottom(currentY)) { return super.dispatchTouchEvent(ev); } return false; } preY = currentY; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: preY = 0; recoverDownView(); if (separate) { separate = false; recoverSeparate(); // 移动,不响应点击事件 if (move) { move = false; return false; } } break; } return super.dispatchTouchEvent(ev); }
3.在dispatchTouchEvent的MotionEvent.ACTION_MOVE事件中检测有没有滑动到最顶部和最底部,如果滑动到最底部则执行上拉的弹性效果。如果滑动到最顶部则实现下拉的弹性效果。
case MotionEvent.ACTION_MOVE: // 记录到达顶部或底部时手指的位置 if (!separate) { startY = currentY; } deltaY = currentY - startY; // 到达顶部 if (reachTop) { if (!separateFromTop(currentY)) { return super.dispatchTouchEvent(ev); } return false; } // 到达底部 if (reachBottom) { if (!separateFromBottom(currentY)) { return super.dispatchTouchEvent(ev); } return false; } preY = currentY; break;
4.弹性效果的实现,for循环遍历每一个Item,根据每个item的索引(position),计算每一个item在Y方向上的偏移量,在每个item的Y方向执行属性动画。
for (int index = 0; index < getChildCount(); index++) { View child = getChildAt(index); int multiple = index; if (!separateAll) { if (index > downPosition) { multiple = Math.max(1, downPosition); } } float distance = multiple * deltaY * FACTOR; child.setTranslationY(distance); }
5.松开手指,恢复到原来的状态,实现原理:遍历每一个Item实现,将每一个Y方向上的偏移量(offsetY)置为0,通过属性动画将状态复原。
/** * 恢复 */ private void recoverSeparate() { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); ViewPropertyAnimator.animate(child).translationY(0) .setDuration(SEPARATE_RECOVER_DURATION) .setInterpolator(new AccelerateInterpolator()); } }
相关文章推荐
- Nginx
- Maven pom.xml 文件报错
- ExpressCache : Product is not licensed to run on this system
- Nmap之概述及工作原理
- WP8加入自己定义铃声
- 来看看Meteor的功能
- Python 入门简介(一)
- UEFI+GPT+WIN7无法使用智能响应技术
- Btrfs文件系统及应用
- IQ , EQ ,...还有什么Q
- 映泰主板BIOS刷入slic并激活
- C#_StreamReader读取文本文件
- 一、原生js,ajax
- python "".join() 出错TypeError: sequence item 0: expected string
- 同时打开多个独立Excel窗口
- Win7 更新到IE11 打开组策略管理模板报错
- Java中的锁——队列同步器
- python脚本在Windows计划任务执行问题
- Oracle中的通配符
- Java中的锁——队列同步器(AQS)