资讯专栏INFORMATION COLUMN

自定义ScrollView 实现上拉下拉的回弹效果--并且子控件中有Viewpager的情况

mating / 487人阅读

摘要:就是对子控件中的处理左右滑动应该让消费获取子视图上一次轴方向操作的坐标位置用于记录临界状态的左上右下是否动画结束拦截实现父视图对子视图的拦截是否拦截成功,取决于方法的返回值。返回值拦截成功。即表示,仍按照的方式处理

onInterceptTouchEvent就是对子控件中Viewpager的处理:左右滑动应该让viewpager消费

  1 public class MyScrollView extends ScrollView {
  2 
  3     private View childView;
  4 
  5     public MyScrollView(Context context) {
  6         super(context);
  7     }
  8 
  9     public MyScrollView(Context context, AttributeSet attrs) {
 10         super(context, attrs);
 11     }
 12 
 13     public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
 14         super(context, attrs, defStyleAttr);
 15     }
 16 
 17 //    @Override
 18 //    protected void onLayout(boolean changed, int l, int t, int r, int b) {
 19 //        super.onLayout(changed, l, t, r, b);
 20 //    }
 21 
 22     //获取子视图
 23     @Override
 24     protected void onFinishInflate() {
 25         super.onFinishInflate();
 26         if (getChildCount() > 0) {
 27             childView = getChildAt(0);
 28         }
 29     }
 30 
 31     private int lastY;//上一次y轴方向操作的坐标位置
 32     private Rect normal = new Rect();//用于记录临界状态的左、上、右、下
 33     private boolean isFinishAnimation = true;//是否动画结束
 34 
 35     private int lastX, downX, downY;
 36 
 37     //拦截:实现父视图对子视图的拦截
 38     //是否拦截成功,取决于方法的返回值。返回值true:拦截成功。反之,拦截失败
 39     @Override
 40     public boolean onInterceptTouchEvent(MotionEvent ev) {
 41         boolean isIntercept = false;
 42         int eventX = (int) ev.getX();
 43         int eventY = (int) ev.getY();
 44         switch (ev.getAction()) {
 45             case MotionEvent.ACTION_DOWN:
 46                 lastX = downX = eventX;
 47                 lastY = downY = eventY;
 48                 break;
 49             case MotionEvent.ACTION_MOVE:
 50                 //获取水平和垂直方向的移动距离
 51                 int absX = Math.abs(eventX - downX);
 52                 int absY = Math.abs(eventY - downY);
 53 
 54                 if(absY > absX && absY >= UIUtils.dp2px(10)){
 55                     isIntercept = true;//执行拦截
 56                 }
 57 
 58                 lastX = eventX;
 59                 lastY = eventY;
 60                 break;
 61         }
 62 
 63         return isIntercept;
 64     }
 65 
 66     @Override
 67     public boolean onTouchEvent(MotionEvent ev) {
 68         if (childView == null || !isFinishAnimation) {
 69             return super.onTouchEvent(ev);
 70         }
 71 
 72         int eventY = (int) ev.getY();//获取当前的y轴坐标
 73         switch (ev.getAction()) {
 74             case MotionEvent.ACTION_DOWN:
 75                 lastY = eventY;
 76                 break;
 77             case MotionEvent.ACTION_MOVE:
 78 
 79                 int dy = eventY - lastY;//微小的移动量
 80 
 81                 if (isNeedMove()) {
 82                     if (normal.isEmpty()) {
 83                         //记录了childView的临界状态的左、上、右、下
 84                         normal.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());
 85 
 86                     }
 87                     //重新布局
 88                     childView.layout(childView.getLeft(), childView.getTop() + dy / 2, childView.getRight(), childView.getBottom() + dy / 2);
 89                 }
 90 
 91                 lastY = eventY;//重新赋值
 92                 break;
 93             case MotionEvent.ACTION_UP:
 94                 if (isNeedAnimation()) {
 95                     //使用平移动画
 96                     int translateY = childView.getBottom() - normal.bottom;
 97                     TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, -translateY);
 98                     translateAnimation.setDuration(200);
 99 //                translateAnimation.setFillAfter(true);//停留在最终位置上
100 
101                     translateAnimation.setAnimationListener(new Animation.AnimationListener() {
102                         @Override
103                         public void onAnimationStart(Animation animation) {
104                             isFinishAnimation = false;
105                         }
106 
107                         @Override
108                         public void onAnimationEnd(Animation animation) {
109                             isFinishAnimation = true;
110                             childView.clearAnimation();//清除动画
111                             //重新布局
112                             childView.layout(normal.left, normal.top, normal.right, normal.bottom);
113                             //清除normal的数据
114                             normal.setEmpty();
115                         }
116 
117                         @Override
118                         public void onAnimationRepeat(Animation animation) {
119 
120                         }
121                     });
122 
123                     //启动动画
124                     childView.startAnimation(translateAnimation);
125                 }
126 
127 
128                 break;
129         }
130 
131 
132         return super.onTouchEvent(ev);
133     }
134 
135     //判断是否需要执行平移动画
136     private boolean isNeedAnimation() {
137         return !normal.isEmpty();
138 
139     }
140 
141     private boolean isNeedMove() {
142         int childMeasuredHeight = childView.getMeasuredHeight();//获取子视图的高度
143         int scrollViewMeasuredHeight = this.getMeasuredHeight();//获取布局的高度
144 
145         Log.e("TAG", "childMeasuredHeight = " + childMeasuredHeight);
146         Log.e("TAG", "scrollViewMeasuredHeight = " + scrollViewMeasuredHeight);
147 
148         int dy = childMeasuredHeight - scrollViewMeasuredHeight;//dy >= 0
149 
150         int scrollY = this.getScrollY();//获取用户在y轴方向上的偏移量 (上 + 下 -)
151         if (scrollY <= 0 || scrollY >= dy) {
152             return true;//按照我们自定义的MyScrollView的方式处理
153         }
154         //其他处在临界范围内的,返回false。即表示,仍按照ScrollView的方式处理
155         return false;
156     }
157 }

 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/3101.html

相关文章

  • 商品详情页上拉查看详情

    摘要:商品详情页上拉查看详情目录介绍该库介绍效果展示如何使用注意要点优化问题部分代码逻辑参考案例该库介绍模仿淘宝京东考拉等商品详情页分页加载的效果。 商品详情页上拉查看详情 目录介绍 01.该库介绍 02.效果展示 03.如何使用 04.注意要点 05.优化问题 06.部分代码逻辑 07.参考案例 01.该库介绍 模仿淘宝、京东、考拉等商品详情页分页加载的UI效果。可以嵌套Recycl...

    Apollo 评论0 收藏0
  • TwinklingRefreshLayout 小而强大刷新控件带顺滑越界回弹,v1.04 版

    摘要:为了达到更好的显示效果,最好禁用系统的,如上给添加。头部固定高度在此高度上显示刷新状态底部高度设置最大的越界高度灵活的设置是否禁用上下拉。是否允许越界回弹。表示向上拉下拉释放时回调的状态。 TwinklingRefreshLayout v1.04 版精心重构,优化 UI、刷新及越界动画效果,修复众多 bug,完美发布!TwinklingRefreshLayout延伸了Google的Sw...

    2501207950 评论0 收藏0
  • TwinklingRefreshLayout 小而强大刷新控件带顺滑越界回弹,v1.04 版

    摘要:为了达到更好的显示效果,最好禁用系统的,如上给添加。头部固定高度在此高度上显示刷新状态底部高度设置最大的越界高度灵活的设置是否禁用上下拉。是否允许越界回弹。表示向上拉下拉释放时回调的状态。 TwinklingRefreshLayout v1.04 版精心重构,优化 UI、刷新及越界动画效果,修复众多 bug,完美发布!TwinklingRefreshLayout延伸了Google的Sw...

    lentrue 评论0 收藏0
  • TwinklingRefreshLayout 小而强大刷新控件带顺滑越界回弹,v1.04 版

    摘要:为了达到更好的显示效果,最好禁用系统的,如上给添加。头部固定高度在此高度上显示刷新状态底部高度设置最大的越界高度灵活的设置是否禁用上下拉。是否允许越界回弹。表示向上拉下拉释放时回调的状态。 TwinklingRefreshLayout v1.04 版精心重构,优化 UI、刷新及越界动画效果,修复众多 bug,完美发布!TwinklingRefreshLayout延伸了Google的Sw...

    xioqua 评论0 收藏0
  • TwinklingRefreshLayout 小而强大刷新控件带顺滑越界回弹,v1.04 版

    摘要:为了达到更好的显示效果,最好禁用系统的,如上给添加。头部固定高度在此高度上显示刷新状态底部高度设置最大的越界高度灵活的设置是否禁用上下拉。是否允许越界回弹。表示向上拉下拉释放时回调的状态。 TwinklingRefreshLayout v1.04 版精心重构,优化 UI、刷新及越界动画效果,修复众多 bug,完美发布!TwinklingRefreshLayout延伸了Google的Sw...

    yuanzhanghu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<