自定义布局---竖向的ViewPager

效果图:

这里写图片描述

这个自定义控件涉及到的知识点:

自定义ViewGroup中onMeasure和onLayout的写法
弹性滚动Scroller的用法
速度轨迹追踪器VelocityTracker的用法
如何处理滑动事件冲突

dispatchTouchEvent:(外部拦截)告诉此ScrollLayout的父布局,什么时候该拦截触摸事件,什么时候不该拦截触摸事件

onInterceptTouchEvent:(内部拦截)ScrollLayout告诉自己什么时候要拦截内部子View的触摸事件,什么时候不要拦截内部子View的触摸事件

处理触摸滑动的思路:

  1. 先实现布局跟着手指的滑动而滑动 scrollBy
  2. 处理好边界条件(这次的处理边界,仅适用于低速滑动情况下)
  3. 如果是快速滑动VelocityTracker,必须再次考虑边界问题(上面考虑的边界问题不适用于快速滑动情况)
  4. 如果是低速滑动,要根据手指滑动方向和布局滑动的距离一起做判断,来确定,页面该滑动到那个页面,这里用到了弹性滑动Scroller
  5. 难点来了:算法,
    • 即确定当前显示的子控件的位置,
    • 确定弹性滑动滑向那个位置
      if (Math.abs(velocityY) > criticalVelocityY) {//当手指滑动速度快时,按照速度方向直接翻页
      // 重点二、快速滑动时,如何判断当前显示的是第几个控件,并且再次包含边界判断(必须包含边界判断,因为前面的边界判断,只适用于低速滑动时)
      if (shouZhiXiangXiaHuaDong) {
      if (currentPage > 1) {//★★★★★★★★边界限制,防止滑倒第一个,还继续滑动,注意★(currentPage-2)
      mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 2) - getScrollY());
      currentPage--;
      }
      } else {
      if (currentPage < childCount) {//★★★★★★★边界限制,防止滑倒最后一个,还继续滑动,注意★currentPage
      mScroller.startScroll(0, getScrollY(), 0, childHeight * currentPage - getScrollY());
      currentPage++;
      }
      }
      Log.e("eee", currentPage + "");

总结

当要写一个算法时,不要着急试图一下子写出来,这样往往陷入盲目,应该是一步一步地推导,一步一步实现代码,指导最后找到规律,类似于归纳总结、通项公式的方法。

代码如下:(注释很全)

package beautlful.time.com.beautlfultime.view;

import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.util.Log;
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只适用于每个子控件为match_parent的情况,其实一般情况也都是这种情况
 * 注意:此自定义viewgroup,没有考虑padding的情况,使用者不要在ScrollerLayout里使用任何padding,否则你看到的不是你想要的,
 * 为了实现padding效果,你可以为ScrollerLayout的外层再套一层线性布局(或其他布局),在外层布局里使用padding值
 * 此自定义viewgroup基于郭霖博客改编,想了解具体实现细节,请参照:
 * Android Scroller完全解析,关于Scroller你所需知道的一切
 * http://blog.youkuaiyun.com/guolin_blog/article/details/48719871
 */
public class VerticalViewPager extends ViewGroup {
   
    int currentPage = 1;

    /**
     * 速度轨迹追踪器
     */
    private VelocityTracker mVelocityTracker;

    /**
     * 此次计算速度你想要的最大值
     */
    private final int mMaxVelocity;

    /**
     * 第一个触点的id, 此时可能有多个触点,但至少一个
     */
    private int mPointerId;

    /**
     * 计算出的竖向滚动速率
     */
    private float velocityY;

    /**
     * 手指横向滑动的速率临界值,大于这个值时,不考虑手指滑动的距离,直接滚动到最左边或者最右边
     */
    private int criticalVelocityY = 2500;

    /**
     * 用于完成滚动操作的实例
     */
    private Scroller mScroller;

    /**
     * 判定为拖动的最小移动像素数
     */
    private int mTouchSlop;

    /**
     * 手机按下时的屏幕坐标
     */
    private float mYDown;

    /**
     * 手机当时所处的屏幕坐标
     */
    private float mYMove;

    /**
     * 上次触发ACTION_MOVE事件时的屏幕坐标
     */
    private float mYLastMove;

    /**
     * 界面可滚动的顶部边界
     */
    private int topBorder;

    /**
     * 界面可滚动的底部边界
     */
  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值