当前位置:   article > 正文

android自定义控件Group之上下滑动回弹及快速滑动手势viewgroup_android 自定义viewgroup 左右上下滑动

android 自定义viewgroup 左右上下滑动

最近一周工作上比较闲,想来没有事做,,于是就想写个自定义控件巩固一下android的自定义控件开发,一开始的想法就是写一个简单的上下翻页的viewGroup,我们都知道viewpager是左右滑动的控件。

还是老规矩,先上效果图:

以上就是效果图,补充说一下实现的效果:实现子控件根据手势上下滑动翻页,慢速滑动过半时会翻页,快速滑动速度达到1000px/s时也会翻页,当然也要首页和尾页处理,首页和尾页部分不论向下或者向上翻动多少都会回弹;在事件分发上也有处理,当触摸或者滑动距离不会大于系统touchslop时就会当做点击事件来处理

到了上代码的时候了:

  1. package com.xuganwen.testviewgroup2;
  2. import android.content.Context;
  3. import android.support.v4.view.ViewConfigurationCompat;
  4. import android.util.AttributeSet;
  5. import android.view.MotionEvent;
  6. import android.view.VelocityTracker;
  7. import android.view.View;
  8. import android.view.ViewConfiguration;
  9. import android.view.ViewGroup;
  10. import android.widget.Scroller;
  11. /**
  12. * 文件描述:上下滑动viewgroup
  13. * 作者:xuganwen
  14. * 创建时间:2019/5/8
  15. * 更改时间:2019/5/8
  16. * 版本号:1.0
  17. */
  18. public class VerticalViewPager extends ViewGroup {
  19. private Scroller mScroller;
  20. private int childCount;
  21. private float downY;
  22. private int touchSlop;
  23. private int scrollY;
  24. private int position;
  25. private VelocityTracker velocityTracker;
  26. public VerticalViewPager(Context context) {
  27. super(context);
  28. }
  29. public VerticalViewPager(Context context, AttributeSet attrs) {
  30. super(context, attrs);
  31. mScroller = new Scroller(context);
  32. touchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(ViewConfiguration.get(context));
  33. }
  34. public VerticalViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
  35. super(context, attrs, defStyleAttr);
  36. }
  37. @Override
  38. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  39. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  40. childCount = getChildCount();
  41. for (int i = 0; i < childCount; i++) {
  42. measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
  43. }
  44. }
  45. @Override
  46. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  47. for (int i = 0; i < childCount; i++) {
  48. View child = getChildAt(i);
  49. child.layout(l, child.getMeasuredHeight() * i, r, child.getMeasuredHeight() * (i + 1));
  50. }
  51. }
  52. @Override
  53. public boolean onTouchEvent(MotionEvent event) {
  54. if(null==velocityTracker){
  55. velocityTracker=VelocityTracker.obtain();
  56. }
  57. velocityTracker.addMovement(event);
  58. switch (event.getAction()) {
  59. case MotionEvent.ACTION_DOWN:
  60. downY = event.getY();
  61. break;
  62. case MotionEvent.ACTION_MOVE:
  63. float moveY = event.getY();
  64. int deltaY = (int) (moveY - downY);
  65. scrollY = getScrollY();
  66. position = getScrollY() % getMeasuredHeight() > getMeasuredHeight() / 2
  67. ? getScrollY() / getMeasuredHeight() + 1
  68. : getScrollY() / getMeasuredHeight();
  69. if (position >= getChildCount()-1) {
  70. position = getChildCount()-1;
  71. }else if(position<=0){
  72. position=0;
  73. }
  74. scrollBy(0, -deltaY);
  75. downY = moveY;
  76. break;
  77. case MotionEvent.ACTION_UP:
  78. if(null!=velocityTracker){
  79. velocityTracker.computeCurrentVelocity(1000);
  80. }
  81. if(Math.abs(velocityTracker.getYVelocity())>1000){
  82. if(velocityTracker.getYVelocity()>1000){
  83. mScroller.startScroll(0, getScrollY(), 0, (position==0?0:position-1) * getMeasuredHeight() - getScrollY());
  84. }else if(velocityTracker.getYVelocity()<-1000){
  85. mScroller.startScroll(0, getScrollY(), 0, (position==getChildCount()-1?getChildCount()-1:(position+1)) * getMeasuredHeight() - getScrollY());
  86. }
  87. }else {
  88. mScroller.startScroll(0, getScrollY(), 0, position * getMeasuredHeight() - getScrollY());
  89. }
  90. invalidate();
  91. release();
  92. break;
  93. case MotionEvent.ACTION_CANCEL:
  94. release();
  95. break;
  96. }
  97. return true;
  98. }
  99. @Override
  100. public boolean dispatchTouchEvent(MotionEvent ev) {
  101. return super.dispatchTouchEvent(ev);
  102. }
  103. @Override
  104. public boolean onInterceptTouchEvent(MotionEvent ev) {
  105. switch (ev.getAction()) {
  106. case MotionEvent.ACTION_DOWN:
  107. downY = ev.getY();
  108. break;
  109. case MotionEvent.ACTION_MOVE:
  110. if(Math.abs(ev.getY()-downY)>touchSlop){
  111. return true;
  112. }
  113. break;
  114. case MotionEvent.ACTION_UP:
  115. break;
  116. }
  117. return false;
  118. }
  119. @Override
  120. public void computeScroll() {
  121. if (mScroller.computeScrollOffset()) {
  122. //这里调用View的scrollTo() 完成实际的滚动
  123. scrollTo(0, mScroller.getCurrY());
  124. //必须调用该方法,否则不一定能看到滚动效果
  125. invalidate();
  126. }
  127. super.computeScroll();
  128. }
  129. public void release(){
  130. if(velocityTracker!=null){
  131. velocityTracker.clear();
  132. velocityTracker.recycle();
  133. velocityTracker=null;
  134. }
  135. }
  136. }

代码如上,可以看得出来滑动效果是通过scroller滑动计算的距离来实现的,滑动速度处理方面是 使用的VelocityTracker来处理的。子控件的点击事件是通过onInterceptouchevent来处理的。

说实话我想了一下,我这个控件应该是支持放入布局类控件作为子控件的,然后使用framgment替换布局来实现放入fragment来实现fragment上下翻页界面效果的,不知道各位有什么看法没,可以提出来讨论讨论~

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号