开袋即食

  1. import android.content.Context;
  2. import android.graphics.Rect;
  3. import android.util.AttributeSet;
  4. import android.view.MotionEvent;
  5. import android.view.View;
  6. import android.view.animation.TranslateAnimation;
  7. import android.widget.ScrollView;
  8.  
  9. /**
  10. * 有弹性的ScrollView
  11. * 实现下拉弹回和上拉弹回
  12. *
  13. * @author zhangjg
  14. * @date Feb 13, 2014 6:11:33 PM
  15. */
  16. public class ReboundScrollView extends ScrollView {
  17.  
  18. private static final String TAG = "ElasticScrollView";
  19.  
  20. //移动因子, 是一个百分比, 比如手指移动了100px, 那么View就只移动50px
  21. //目的是达到一个延迟的效果
  22. private static final float MOVE_FACTOR = 0.5f;
  23.  
  24. //松开手指后, 界面回到正常位置需要的动画时间
  25. private static final int ANIM_TIME = 300;
  26.  
  27. //ScrollView的子View, 也是ScrollView的唯一一个子View
  28. private View contentView;
  29.  
  30. //手指按下时的Y值, 用于在移动时计算移动距离
  31. //如果按下时不能上拉和下拉, 会在手指移动时更新为当前手指的Y值
  32. private float startY;
  33.  
  34. //用于记录正常的布局位置
  35. private Rect originalRect = new Rect();
  36.  
  37. //手指按下时记录是否可以继续下拉
  38. private boolean canPullDown = false;
  39.  
  40. //手指按下时记录是否可以继续上拉
  41. private boolean canPullUp = false;
  42.  
  43. //在手指滑动的过程中记录是否移动了布局
  44. private boolean isMoved = false;
  45.  
  46. public ReboundScrollView(Context context) {
  47. super(context);
  48. }
  49.  
  50. public ReboundScrollView(Context context, AttributeSet attrs) {
  51. super(context, attrs);
  52. }
  53.  
  54. @Override
  55. protected void onFinishInflate() {
  56. if (getChildCount() > 0) {
  57. contentView = getChildAt(0);
  58. }
  59. }
  60.  
  61. @Override
  62. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  63. super.onLayout(changed, l, t, r, b);
  64.  
  65. if (contentView == null) return;
  66.  
  67. //ScrollView中的唯一子控件的位置信息, 这个位置信息在整个控件的生命周期中保持不变
  68. originalRect.set(contentView.getLeft(), contentView.getTop(), contentView
  69. .getRight(), contentView.getBottom());
  70. }
  71.  
  72. /**
  73. * 在触摸事件中, 处理上拉和下拉的逻辑
  74. */
  75. @Override
  76. public boolean dispatchTouchEvent(MotionEvent ev) {
  77.  
  78. if (contentView == null) {
  79. return super.dispatchTouchEvent(ev);
  80. }
  81.  
  82. int action = ev.getAction();
  83.  
  84. switch (action) {
  85. case MotionEvent.ACTION_DOWN:
  86.  
  87. //判断是否可以上拉和下拉
  88. canPullDown = isCanPullDown();
  89. canPullUp = isCanPullUp();
  90.  
  91. //记录按下时的Y值
  92. startY = ev.getY();
  93. break;
  94.  
  95. case MotionEvent.ACTION_UP:
  96.  
  97. if (!isMoved) break; //如果没有移动布局, 则跳过执行
  98.  
  99. // 开启动画
  100. TranslateAnimation anim = new TranslateAnimation(0, 0, contentView.getTop(),
  101. originalRect.top);
  102. anim.setDuration(ANIM_TIME);
  103.  
  104. contentView.startAnimation(anim);
  105.  
  106. // 设置回到正常的布局位置
  107. contentView.layout(originalRect.left, originalRect.top,
  108. originalRect.right, originalRect.bottom);
  109.  
  110. //将标志位设回false
  111. canPullDown = false;
  112. canPullUp = false;
  113. isMoved = false;
  114.  
  115. break;
  116. case MotionEvent.ACTION_MOVE:
  117.  
  118. //在移动的过程中, 既没有滚动到可以上拉的程度, 也没有滚动到可以下拉的程度
  119. if (!canPullDown && !canPullUp) {
  120. startY = ev.getY();
  121. canPullDown = isCanPullDown();
  122. canPullUp = isCanPullUp();
  123.  
  124. break;
  125. }
  126.  
  127. //计算手指移动的距离
  128. float nowY = ev.getY();
  129. int deltaY = (int) (nowY - startY);
  130.  
  131. //是否应该移动布局
  132. boolean shouldMove =
  133. (canPullDown && deltaY > 0) //可以下拉, 并且手指向下移动
  134. || (canPullUp && deltaY < 0) //可以上拉, 并且手指向上移动
  135. || (canPullUp && canPullDown); //既可以上拉也可以下拉(这种情况出现在ScrollView包裹的控件比ScrollView还小)
  136.  
  137. if (shouldMove) {
  138. //计算偏移量
  139. int offset = (int) (deltaY * MOVE_FACTOR);
  140.  
  141. //随着手指的移动而移动布局
  142. contentView.layout(originalRect.left, originalRect.top + offset,
  143. originalRect.right, originalRect.bottom + offset);
  144.  
  145. isMoved = true; //记录移动了布局
  146. }
  147.  
  148. break;
  149. default:
  150. break;
  151. }
  152.  
  153. return super.dispatchTouchEvent(ev);
  154. }
  155.  
  156. /**
  157. * 判断是否滚动到顶部
  158. */
  159. private boolean isCanPullDown() {
  160. return getScrollY() == 0 ||
  161. contentView.getHeight() < getHeight() + getScrollY();
  162. }
  163.  
  164. /**
  165. * 判断是否滚动到底部
  166. */
  167. private boolean isCanPullUp() {
  168. return contentView.getHeight() <= getHeight() + getScrollY();
  169. }
  170.  
  171. }

Android弹性ScrollView的更多相关文章

  1. 弹性ScrollView,和下啦刷新的效果类似 实现下拉弹回和上拉弹回

    今天做了一个弹性ScrollView,和下啦刷新的效果类似,我想这个很多需求都用的这种效果 其实这是一个自定义的scrollView,上代码,这是我写在一个公共的组件包里的 package com.p ...

  2. 弹性ScrollView,和下啦刷新的效果相似 实现下拉弹回和上拉弹回

    今天做了一个弹性ScrollView,和下啦刷新的效果类似,我想这个非常多需求都用的这样的效果 事实上这是一个自己定义的scrollView,上代码.这是我写在一个公共的组件包里的 package c ...

  3. android 自定义scrollview 仿QQ空间效果 下拉伸缩顶部图片,上拉回弹 上拉滚动顶部title 颜色渐变

    首先要知道  自定义scrollview 仿QQ效果 下拉伸缩放大顶部图片 的原理是监听ontouch事件,在MotionEvent.ACTION_MOVE事件时候,使用不同倍数的系数,重置布局位置[ ...

  4. Android自定义ScrollView分段加载大文本数据到TextView

    以下内容为原创,转载时请注明链接地址:http://www.cnblogs.com/tiantianbyconan/p/3311658.html 这是我现在碰到的一个问题,如果需要在TextView中 ...

  5. Android自定义ScrollView实现一键置顶功能

    效果图如下: (ps:动态图有太大了,上传不了,就给大家口述一下要实现的功能吧) 要实现的功能:当ScrollView向上滑动超过一定距离后,就渐变的出现一个置顶的按钮,当滑动距离小于我们指定的距离时 ...

  6. Android 自定义ScrollView ListView 体验各种纵向滑动的需求

      分类: [android 进阶之路]2014-08-31 12:59 6190人阅读 评论(10) 收藏 举报 Android自定义ScrollView纵向拖动     转载请标明出处:http: ...

  7. Android开发ScrollView上下左右滑动事件冲突整理一(根据事件)

    主要通过重写 onInterceptTouchEvent 事件来解决,代码如下: package com.cm.android.pad.view.itemView; import android.co ...

  8. Android对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果

    转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17761431),请尊重他人的辛勤劳动成果,谢谢! 我之前写 ...

  9. Android 屏蔽ScrollView滑动操作

    屏蔽ScrollView滑动操作,如下,会用到ViewConfiguration这个类,这个类可以获取到用户是否为滑动操作的临界值. 代码如下: package com.xx.uikit.view; ...

随机推荐

  1. 让 zend studio 识别 Phalcon语法并且进行语法提示

    让 zend studio  识别 Phalcon语法并且进行语法提示 https://github.com/phalcon/phalcon-devtools/tree/master/ide 下载解压 ...

  2. C# web访问mysql数据库-整理归纳总结

    基本对比 使用方式 使用场合 优缺点 是否需要安装 需要的dll网址 引用方式 程序内引用 程序初期确定使用MySql,前期添加引用 大多数情况下使用在类文件内,多数使用于aspx,ashx等带有后置 ...

  3. Android UI开发第三十一篇——Android的Holo Theme

    好长时间没写Android UI方面的文章了,今天就闲扯一下Android的Holo主题.一直做android开发的可能都知道,Android 系统的UI有过两次大的变化,一次是android 3.0 ...

  4. COJ 0650 绝世难题(一) 可爱的仙人掌

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=620 绝世难题(一) 可爱的仙人掌 难度级别:E: 运行时间限制:1000m ...

  5. HDFS基础和java api操作

    1. 概括 适合一次写入多次查询情况,不支持并发写情况 通过hadoop shell 上传的文件存放在DataNode的block中,通过linux shell只能看见block,看不见文件(HDFS ...

  6. Tuna项目总结

    从8.19—9.13日一共四周的时间,我在Tuna项目组进行的我的第一次正式工作,以及学习.在此,我对这个阶段的工作及学习进行一个总结,主要分为对流程的理解和对自动化测试的应用两个方面. 在总结着两点 ...

  7. 尚学堂 JAVA Day1 概念总结

    1.什么是计算机语言?一些符号,这些符号按照计算机硬件结构可以理解的方式排列组合,方便人与计算机,计算机与计算机之间进行信息的交换. 2.什么是机器语言?就是简单的二进制0和1的组合.该语言是计算机硬 ...

  8. I - Agri-Net - poj 1258

    貌似就是个裸的最小生成树啊 ******************************************************************************* #inclu ...

  9. oracle防火墙端口问题

    Oracle服务端口方面会有很多的问题,下面就将为您介绍在防火墙上开放Oracle服务端口的方法,希望对您学习Oracle服务端口方面能有所帮助. 要使Oracle客户端能正常连接到设置有防火墙的安装 ...

  10. redis在Java web项目的简单应用(转载)

    看到一篇关于redis和spring集成的文章,实际测试后,可以.转载以备用.谢谢 亲昵YY! html,body { font-size: 15px } body { font-family: He ...