自定义仿Viewpager

来源:互联网 发布:大数据是一种思维方式 编辑:程序博客网 时间:2024/06/05 23:53

自定义仿Viewpager

public class MyViewPager extends ViewGroup {    /**     * 手势识别器     * 在onTouchEvent方法中把事件传递给手势识别器     */    private GestureDetector detector;    /**     * 当前页面的下标位置     */    private int currentIndex;    /**     * 起始坐标位置     */    private float startX;    public MyViewPager(Context context, AttributeSet attrs) {        super(context, attrs);        initView(context);    }    private void initView(final Context context) {        /**         * 实例化手势识别器         */        detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {//            /**//             * 长按//             * @param e//             *///            @Override//            public void onLongPress(MotionEvent e) {//                super.onLongPress(e);//                Toast.makeText(context, "长按", Toast.LENGTH_SHORT).show();//            }////            /**//             * 双击//             * @param e//             * @return//             *///            @Override//            public boolean onDoubleTap(MotionEvent e) {//                Toast.makeText(context, "双击", Toast.LENGTH_SHORT).show();//                return super.onDoubleTap(e);//            }            /**             * 滑动             * @param e1 按下             * @param e2 放开             * @param distanceX 横坐标滑动的距离             * @param distanceY 纵坐标滑动的距离             * @return             */            @Override            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {                /**                 * 通过此方法实现滑动                 */                scrollBy((int) distanceX, 0);                return true;            }        });    }    /**     * 布局     *     * @param changed     * @param l       左上角横坐标     * @param t       左上角纵坐标     * @param r       右下角横坐标     * @param b       右下角纵坐标     */    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        // 遍历子View并为其指定在屏幕的坐标位置        for (int i = 0; i < getChildCount(); i++) {            View childAt = getChildAt(i);            childAt.layout(i * getWidth(), 0, (i + 1) * getWidth(), getHeight());        }    }    /**     * 测量     * 根据widthMeasureSpec求得宽度width和父View给的模式     * 根据自身宽度width和自身的padding值相减,求得子view可以获得的宽度newWidth     * 根据newWidth和模式求得一个新的MeasureSpec值:     * MeasureSpec.makeMeasureSpec(newSize,newMode);     * 用新的MeasureSpec来计算子View     *     * @param widthMeasureSpec  父层视图给当前视图的宽和模式     * @param heightMeasureSpec 系统测量时测量多次     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int sizeW = MeasureSpec.getSize(widthMeasureSpec);        int modeW = MeasureSpec.getMode(widthMeasureSpec);        int sizeH = MeasureSpec.getSize(heightMeasureSpec);        int modeH = MeasureSpec.getMode(heightMeasureSpec);        Log.e("sizeW=", sizeW + "");        Log.e("modeW=", modeW + "");        Log.e("sizeH=", sizeH + "");        Log.e("modeH=", modeH + "");        for (int i = 0; i < getChildCount(); i++) {            View childAt = getChildAt(i);            // 测量每个子View的宽高            childAt.measure(widthMeasureSpec, heightMeasureSpec);        }    }    /**     * 事件的分发     * Android中所有的事件都必须经过这个方法的分发,然后决定是自身消费当前事件     * 还是继续分发给子控件处理     * 返回true表示不继续分发,事件没有被消费,返回false则继续向下分发     * 如果是ViewGroup则分发给onInterceptTouchEvent进行判断是否拦截     *     * @param ev     * @return     */    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        //TODO 条件        // 将事件分发给孩子        //getChildAt(0).dispatchTouchEvent(ev);        return super.dispatchTouchEvent(ev);    }    private float downX;    private float downY;    /**     * 事件的拦截     * 该方法是ViewGroup特有的方法,负责事件的拦截     * 返回true表示拦截当前事件,不继续往下分发,交给自身的onTouchEvent进行处理     * 返回false则不拦截继续往下传递     *     * @param ev     * @return     */    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        detector.onTouchEvent(ev); //防止突然闪动        //默认传递给孩子        boolean result = false;        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e("onInterceptTouchEvent", "ACTION_DOWN");                // 记录坐标                downX = ev.getX();                downY = ev.getY();                break;            case MotionEvent.ACTION_MOVE:                Log.e("onInterceptTouchEvent", "ACTION_MOVE");                // 记录结束值                float endX = ev.getX();                float endY = ev.getY();                // 计算绝对值                float distanceX = Math.abs(endX - downX);                float distanceY = Math.abs(endY - downY);                if (distanceX > distanceY && distanceX > 5) {                    //如果横向移动距离大于纵向移动距离则拦截事件                    result = true;                }                break;            case MotionEvent.ACTION_UP:                Log.e("onInterceptTouchEvent", "ACTION_UP");                break;        }        return result;    }    /**     * 触摸事件     * 用于事件的处理,返回true表示消费处理当前事件,返回false则不处理     * 交给子控件继续分发     *     * @param event     * @return     */    @Override    public boolean onTouchEvent(MotionEvent event) {        super.onTouchEvent(event);        // 把事件传递给手势识别器        detector.onTouchEvent(event);        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e("onTouchEvent", "ACTION_DOWN");                startX = event.getX();                break;            case MotionEvent.ACTION_MOVE:                Log.e("onTouchEvent", "ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e("onTouchEvent", "ACTION_UP");                float endX = event.getX();                int tmpIndex = currentIndex;                if ((startX - endX) > getWidth() / 2) {                    // 显示下一个页面                    tmpIndex++;                } else if ((endX - startX) > getWidth() / 2) {                    tmpIndex--;                }                /**                 * 根据下标位置移动到指定页面                 */                scrollToPager(tmpIndex);                break;        }        return true;    }    /**     * 屏蔽非法值,根据位置移动到指定页面     *     * @param tmpIndex     */    private void scrollToPager(int tmpIndex) {        if (tmpIndex < 0) {            tmpIndex = 0;        }        if (tmpIndex > getChildCount() - 1) {            tmpIndex = getChildCount() - 1;        }        //当前变量的下标位置        currentIndex = tmpIndex;        /**         * 手放开后自动完成滑动         *         */        //float distanceX  = currentIndex*getWidth()-getScrollX();//        scrollTo(currentIndex*getWidth(),0);        /**         * 使用数值发生器完成剩下的滑动         */        ValueAnimator valueAnimator = ValueAnimator.ofInt(getScrollX(), currentIndex * getWidth());        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                Integer value = (Integer) animation.getAnimatedValue();                scrollTo(value, 0);            }        });        valueAnimator.setDuration(500).start();    }}

这里写图片描述

原创粉丝点击