赞
踩
最近一周工作上比较闲,想来没有事做,,于是就想写个自定义控件巩固一下android的自定义控件开发,一开始的想法就是写一个简单的上下翻页的viewGroup,我们都知道viewpager是左右滑动的控件。
还是老规矩,先上效果图:
以上就是效果图,补充说一下实现的效果:实现子控件根据手势上下滑动翻页,慢速滑动过半时会翻页,快速滑动速度达到1000px/s时也会翻页,当然也要首页和尾页处理,首页和尾页部分不论向下或者向上翻动多少都会回弹;在事件分发上也有处理,当触摸或者滑动距离不会大于系统touchslop时就会当做点击事件来处理
到了上代码的时候了:
- package com.xuganwen.testviewgroup2;
-
- import android.content.Context;
- import android.support.v4.view.ViewConfigurationCompat;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- import android.view.VelocityTracker;
- import android.view.View;
- import android.view.ViewConfiguration;
- import android.view.ViewGroup;
- import android.widget.Scroller;
-
- /**
- * 文件描述:上下滑动viewgroup
- * 作者:xuganwen
- * 创建时间:2019/5/8
- * 更改时间:2019/5/8
- * 版本号:1.0
- */
- public class VerticalViewPager extends ViewGroup {
-
- private Scroller mScroller;
- private int childCount;
- private float downY;
- private int touchSlop;
- private int scrollY;
- private int position;
-
- private VelocityTracker velocityTracker;
-
- public VerticalViewPager(Context context) {
- super(context);
- }
-
- public VerticalViewPager(Context context, AttributeSet attrs) {
- super(context, attrs);
- mScroller = new Scroller(context);
- touchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(ViewConfiguration.get(context));
- }
-
- public VerticalViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
-
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- child.layout(l, child.getMeasuredHeight() * i, r, child.getMeasuredHeight() * (i + 1));
- }
-
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if(null==velocityTracker){
- velocityTracker=VelocityTracker.obtain();
- }
- velocityTracker.addMovement(event);
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- downY = event.getY();
- break;
- case MotionEvent.ACTION_MOVE:
- float moveY = event.getY();
- int deltaY = (int) (moveY - downY);
- scrollY = getScrollY();
- position = getScrollY() % getMeasuredHeight() > getMeasuredHeight() / 2
- ? getScrollY() / getMeasuredHeight() + 1
- : getScrollY() / getMeasuredHeight();
- if (position >= getChildCount()-1) {
- position = getChildCount()-1;
- }else if(position<=0){
- position=0;
- }
- scrollBy(0, -deltaY);
- downY = moveY;
- break;
- case MotionEvent.ACTION_UP:
- if(null!=velocityTracker){
- velocityTracker.computeCurrentVelocity(1000);
- }
- if(Math.abs(velocityTracker.getYVelocity())>1000){
- if(velocityTracker.getYVelocity()>1000){
- mScroller.startScroll(0, getScrollY(), 0, (position==0?0:position-1) * getMeasuredHeight() - getScrollY());
- }else if(velocityTracker.getYVelocity()<-1000){
- mScroller.startScroll(0, getScrollY(), 0, (position==getChildCount()-1?getChildCount()-1:(position+1)) * getMeasuredHeight() - getScrollY());
- }
- }else {
- mScroller.startScroll(0, getScrollY(), 0, position * getMeasuredHeight() - getScrollY());
- }
- invalidate();
- release();
- break;
- case MotionEvent.ACTION_CANCEL:
- release();
- break;
- }
- return true;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- return super.dispatchTouchEvent(ev);
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
-
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- downY = ev.getY();
- break;
- case MotionEvent.ACTION_MOVE:
- if(Math.abs(ev.getY()-downY)>touchSlop){
- return true;
- }
- break;
- case MotionEvent.ACTION_UP:
- break;
- }
- return false;
- }
-
- @Override
- public void computeScroll() {
- if (mScroller.computeScrollOffset()) {
- //这里调用View的scrollTo() 完成实际的滚动
- scrollTo(0, mScroller.getCurrY());
- //必须调用该方法,否则不一定能看到滚动效果
- invalidate();
- }
- super.computeScroll();
- }
-
-
- public void release(){
- if(velocityTracker!=null){
- velocityTracker.clear();
- velocityTracker.recycle();
- velocityTracker=null;
- }
- }
- }

代码如上,可以看得出来滑动效果是通过scroller滑动计算的距离来实现的,滑动速度处理方面是 使用的VelocityTracker来处理的。子控件的点击事件是通过onInterceptouchevent来处理的。
说实话我想了一下,我这个控件应该是支持放入布局类控件作为子控件的,然后使用framgment替换布局来实现放入fragment来实现fragment上下翻页界面效果的,不知道各位有什么看法没,可以提出来讨论讨论~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。