Android实现滑动功能的总结


最近的一个项目仿照百度地图的滑动功能,各种特效的出现着实让我纠结了好几个星期。好在iOS那边好几个版本老板都不满意,这让我有时间来研究滑动的实现了。现在分享下滑动,希望朋友们不会因为滑动个纠结这么久!


一想到滑动,我们肯定会毫不犹豫的想到ScrollView,简单方便,但是我们在使用的时候要注意重写一下两个方法:

 @Override
    public boolean onTouchEvent(MotionEvent ev) { 
        super.onTouchEvent(ev);
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event)
    {
        super.onInterceptTouchEvent(event);
        return false;
    }
屏蔽掉touch事件才能监听子view的touch事件。接下来实现滑动就行
<pre name="code" class="java">@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        int y = 0;
        int offsetY = 0;
        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                point.y = (int) ev.getRawY();
                offset = 0;
                break;
            case MotionEvent.ACTION_MOVE:
                y = (int) ev.getRawY();
                offsetY = y - point.y;
                offset += offsetY;
                point.y = (int) ev.getRawY();
                this.scrollBy(0, -offsetY);
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            case MotionEvent.ACTION_UP:
                if (offset > 0) {
                    if (isOpen) {
                        if (offset > 400) {

                            this.scrollTo(0, 400);
                            isOpen = false;
                        } else {
                            this.scrollTo(0, 400);
                            isOpen = true;
                        }
                    } else {
                        this.scrollTo(0, 0);
                        isOpen = false;
                    }
                } else {// offsetsum小于0时是往上拉,只有当隐藏详情页是下拉才有效果,所以这里先判断isOpen的值。
                    if (!isOpen) {
                        if (offset < -400) {
                            scrollTo(0, 400 - dip2px(getContext(), 200));
                            isOpen = true;
                        } else {
                            scrollTo(0, 0);
                            isOpen = false;
                        }
                    } else {
                        scrollTo(0, 400 - dip2px(getContext(), 200));
                        isOpen = true;
                    }

                }

                break;

        }
        return super.dispatchTouchEvent(ev);

    }

 代码启示很简单吧,只是我们平时都不愿意动手,自己写写还是一下就实现了。 

简单点的就是layout的方法,其实就是上面方法类似的,只不过是在onTouchEvent(MotionEvent event)方法中实现,但是在我这个项目中效果是一样的。但是要注意event.getY()和event.getRawY的区别。

实际上View本身还有scrollTo和scrollBy这两方法,以前都没发现,还以为是ScrollerView专有的,所以在确定偏移量的时候就可以使用者两个方法了。

当然不能忘了Scroller这个类,著名的代表方法就是重写computeScroll()这个方法模拟实现滑动,滑动的时候别忘了刷新invalidate()。

属性动画也是一种措施哦!

当然,还有一种我项目中使用的,这是在一位架构师提醒下才知道有这个强大功能的类:ViewDragHelper。神奇的是这是个v4包里面的,用法也不是想象中的那么艰难。

首先初始化:mViewDragHelper= ViewDragHelper.create(this,1f,newDragHelperCallback());

    拦截事件:

@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);
        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            <span style="color: rgb(102, 14, 122); font-family: Menlo; "><strong>mViewDragHelper</strong></span>.cancel();
            return false;
        }
        return <span style="color: rgb(102, 14, 122); font-family: Menlo; "><strong>mViewDragHelper</strong></span>.shouldInterceptTouchEvent(ev);
    }

处理滑动:computeScroll(),这个很无奈,人家也是需要处理这个东西的。

处理回调:这个是关键点。

 @Override
        public boolean tryCaptureView(View child, int pointerId) {
            if (mViewDragCapture) {
                return child == mDragView1;
            }
            return true;
        }
        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            if (mDragVertical) {
                final int topBound = getPaddingTop();
                final int bottomBound = getHeight() - mDragView1.getHeight();

                final int newTop = Math.min(Math.max(top, topBound), bottomBound);

                return newTop;
            }
            return super.clampViewPositionVertical(child, top, dy);
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            if (mDragHorizontal || mViewDragCapture || mDragEdge) {
                final int leftBound = getPaddingLeft();
                final int rightBound = getWidth() - mDragView1.getWidth();

                final int newLeft = Math.min(Math.max(left, leftBound), rightBound);

                return newLeft;
            }
            return super.clampViewPositionHorizontal(child, left, dx);
        }
这三个方法是必须要实现的,但是可以根据需要进行实现,看方法名字就知道用来干嘛的吧!不要忘了回调结束之后要处理哦!
 @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            invalidate();
        }

        @Override
        public void onViewCaptured(View capturedChild, int activePointerId) {
            super.onViewCaptured(capturedChild, activePointerId);
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
        }

        @Override
        public void onEdgeTouched(int edgeFlags, int pointerId) {
            super.onEdgeTouched(edgeFlags, pointerId);
        }

        @Override
        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
            if (mDragEdge) {
                mDragHelper.captureChildView(mDragView1, pointerId);
            }
        }
具体的实现就交给各位自己去实现了,这仅仅是基本的用法,至于源码什么的还没研究透彻,不好意思放上来,这个以后在补充,菜鸟也是要时间才能长大嘛!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值