zoukankan      html  css  js  c++  java
  • ScrollView反弹效果

      1 public class BounceScrollView extends ScrollView {
      2     private View inner;// 孩子View
      3 
      4     private float y;// 点击时y坐标
      5 
      6     private Rect normal = new Rect();// 矩形(这里只是个形式,只是用于判断是否需要动画.)
      7 
      8     private boolean isCount = false;// 是否开始计算
      9 
     10     public BounceScrollView(Context context, AttributeSet attrs) {
     11         super(context, attrs);
     12     }
     13 
     14     /***
     15      * 根据 XML 生成视图工作完成.该函数在生成视图的最后调用,在所有子视图添加完之后. 即使子类覆盖了 onFinishInflate
     16      * 方法,也应该调用父类的方法,使该方法得以执行.
     17      */
     18     @Override
     19     protected void onFinishInflate() {
     20         if (getChildCount() > 0) {
     21             inner = getChildAt(0);
     22         }
     23     }
     24 
     25     /***
     26      * 监听touch
     27      */
     28     @Override
     29     public boolean onTouchEvent(MotionEvent ev) {
     30         if (inner != null) {
     31             commOnTouchEvent(ev);
     32         }
     33 
     34         return super.onTouchEvent(ev);
     35     }
     36 
     37     /***
     38      * 触摸事件
     39      * 
     40      * @param ev
     41      */
     42     public void commOnTouchEvent(MotionEvent ev) {
     43         int action = ev.getAction();
     44         switch (action) {
     45         case MotionEvent.ACTION_DOWN:
     46             break;
     47         case MotionEvent.ACTION_UP:
     48             // 手指松开.
     49             if (isNeedAnimation()) {
     50                 animation();
     51                 isCount = false;
     52             }
     53             break;
     54         /***
     55          * 排除出第一次移动计算,因为第一次无法得知y坐标, 在MotionEvent.ACTION_DOWN中获取不到,
     56          * 因为此时是MyScrollView的touch事件传递到到了LIstView的孩子item上面.所以从第二次计算开始.
     57          * 然而我们也要进行初始化,就是第一次移动的时候让滑动距离归0. 之后记录准确了就正常执行.
     58          */
     59         case MotionEvent.ACTION_MOVE:
     60             final float preY = y;// 按下时的y坐标
     61             float nowY = ev.getY();// 时时y坐标
     62             int deltaY = (int) (preY - nowY);// 滑动距离
     63             if (!isCount) {
     64                 deltaY = 0; // 在这里要归0.
     65             }
     66 
     67             y = nowY;
     68             // 当滚动到最上或者最下时就不会再滚动,这时移动布局
     69             if (isNeedMove()) {
     70                 // 初始化头部矩形
     71                 if (normal.isEmpty()) {
     72                     // 保存正常的布局位置
     73                     normal.set(inner.getLeft(), inner.getTop(),
     74                             inner.getRight(), inner.getBottom());
     75                 }
     76 //                Log.e("jj", "矩形:" + inner.getLeft() + "," + inner.getTop()
     77 //                        + "," + inner.getRight() + "," + inner.getBottom());
     78                 // 移动布局
     79                 inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2,
     80                         inner.getRight(), inner.getBottom() - deltaY / 2);
     81             }
     82             isCount = true;
     83             break;
     84 
     85         default:
     86             break;
     87         }
     88     }
     89 
     90     /***
     91      * 回缩动画
     92      */
     93     public void animation() {
     94         // 开启移动动画
     95         TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(), normal.top);
     96         ta.setDuration(200);
     97         inner.startAnimation(ta);
     98         // 设置回到正常的布局位置
     99         inner.layout(normal.left, normal.top, normal.right, normal.bottom);
    100 
    101 //        Log.e("jj", "回归:" + normal.left + "," + normal.top + "," + normal.right
    102 //                + "," + normal.bottom);
    103 
    104         normal.setEmpty();
    105 
    106     }
    107 
    108     // 是否需要开启动画
    109     public boolean isNeedAnimation() {
    110         return !normal.isEmpty();
    111     }
    112 
    113     /***
    114      * 是否需要移动布局 inner.getMeasuredHeight():获取的是控件的总高度
    115      * 
    116      * getHeight():获取的是屏幕的高度
    117      * 
    118      * @return
    119      */
    120     public boolean isNeedMove() {
    121         int offset = inner.getMeasuredHeight() - getHeight();
    122         int scrollY = getScrollY();
    123 //        Log.e("jj", "scrolly=" + scrollY);
    124         // 0是顶部,后面那个是底部
    125         if (scrollY == 0 || scrollY == offset) {
    126             return true;
    127         }
    128         return false;
    129     }
    130 
    131 }

    此View用于,在没有充满父级的时候,下拉会有反弹效果。但是Android自带的ScrollView就不可以。

  • 相关阅读:
    第十四节、FAST角点检测(附源码)
    第三十六节,目标检测之yolo源码解析
    《理财市场情绪监测系统》代码实现【1】之行业词库
    python numpy 下载地址
    hive 添加自增列
    excel做回归分析的应用【风控数据分析】
    SELECT a.loginname,a.deviceid,a.time,Row_Number() OVER (partition by a.loginname ORDER BY a.deviceid desc,a.time asc) rank
    hive cst 时间转换
    hive以文件创建表
    以当前日期命名或复制文件夹
  • 原文地址:https://www.cnblogs.com/royi123/p/4257788.html
Copyright © 2011-2022 走看看