lsjwzh / RecyclerViewPager

Deprecated
Apache License 2.0
3.53k stars 667 forks source link

滑动冲突 #141

Open duzechao opened 7 years ago

duzechao commented 7 years ago

我设置的是横向滑动的,然后我的item的view里面是一个可以竖向滑动的TextView,这个时候上下滑动的时候会左右抖动并且上下滑动困难

Kongdy commented 7 years ago

recyclerViewPager是在recyclerView基础上改的,对recyclerView的触摸事件没有做过多的修改,还是recyclerview本来的触摸机制,所以滑动的时候,很容易触发左右滑动效果。这个只能寄希望后面会增加一个触摸拦截。

ShinonomeHana commented 7 years ago

没必要增加触摸拦截 直接新建个类,继承RecyclerViewPager然后重写dispatchTouchEvent方法 判断下角度,如果是垂直滚动,就把return的触摸事件的x值永远设为触摸按下时的x值,类似于直接把触摸事件伪装成一个垂直直线运动就行了

ShinonomeHana commented 7 years ago

就这样了,实现起来丑了点,但效果的确很好


    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch ( ev.getAction()){
            case ACTION_DOWN:
                inHorizonMoving = inVerticalMoving = false;
                startEvent = MotionEvent.obtain( ev );
                Log.d("按下", "按下了" + ev.getX() + "  " + ev.getY());
                return super.dispatchTouchEvent(ev);
            case ACTION_MOVE:
                Log.d("MOVE", "Move中"+ ev.getX() + "  " +ev.getY());

                    float deltaX = Math.abs(startEvent.getX() - ev.getX());
                    float deltaY = Math.abs(startEvent.getY() - ev.getY());
                    float tan = deltaY / deltaX;
                    Log.d("tan", "tan="+ tan);

                    if ( tan < 0.46  ){
                        // 水平滚动
                        Log.d("水平滚动", "水平滚动");
                        inHorizonMoving = true;
                        MotionEvent cloneMotionEvent = MotionEvent.obtain(ev);
                        if ( inVerticalMoving )
                            cloneMotionEvent.setLocation(startEvent.getX(), cloneMotionEvent.getY());
                        else
                            cloneMotionEvent.setLocation(cloneMotionEvent.getX(), startEvent.getY());
                        return super.dispatchTouchEvent(cloneMotionEvent);
                    } else if (Float.isInfinite(tan) || Float.isNaN( tan )) {
                        Log.d("无滚动", "无滚动");
                        return true;
                    } else {
                        // 垂直滚动
                        Log.d("垂直滚动", "垂直滚动");
                        inVerticalMoving = true;
                        MotionEvent cloneMotionEvent = MotionEvent.obtain(ev);
                        if (inHorizonMoving)
                            cloneMotionEvent.setLocation(cloneMotionEvent.getX(), startEvent.getY());
                        else
                            cloneMotionEvent.setLocation(startEvent.getX(), cloneMotionEvent.getY());

                        return super.dispatchTouchEvent(cloneMotionEvent);
                    }
            case ACTION_UP:
                inHorizonMoving = inVerticalMoving = false;
                Log.d("放开", "放开了"+ ev.getX() + "  " + ev.getY());
                startEvent = null;
                return super.dispatchTouchEvent(ev);

        }
        return super.dispatchTouchEvent(ev);
    }`
Kongdy commented 7 years ago

首先有个问题,dispatchTouchEvent是处理事件分发的,这样写会对本身自带的分发产生一定的影响,会产生很多问题。其次,新建一个类不觉得累赘吗?onInterceptTouchEvent是处理触摸拦截的,在这里判断角度,可以完美的避开对本身所产生的影响,考虑某些特殊情况,增加一个字段,直接添加到RecycleViewPager基类,这样,可以做到代码变动做小,而且不会影响之前的机制。

ShinonomeHana commented 7 years ago

内啥,现在的问题是,RecycleViewPager已经一段时间没更新了,寄希望于作者来更新,明显自己写出个方法来对付下解决问题更好。 然后,新建个类累赘吗?上面说了,重要的是解决问题。 你如果真嫌新建个类累赘,那可以把作者整个代码download下来啊,然后把作者这项目作为moudle导入到项目里直接在源代码里改啊,这样就不用新建了类了啊

最后,关于改写onInterceptTouchEvent。我这代码是写给楼主的,只适用楼主这种水平嵌套垂直的条件情况。你具体说说吧,针对楼主这情况我这代码会产生什么很多问题? 再说了,有问题了你不会自己针对问题来改啊,我这代码已经简单易懂到这地步了,自己改改不就行了

Kongdy commented 7 years ago

我之前就写好了,在pull Requests里,看作者意思,合不合这个代码。

ShinonomeHana commented 7 years ago

你也看到了嘛……作者一个月都没动静了,issues也有那么多条没理了。 issues的意义就是解决发issue的人的问题,能解决问题是最重要的。开发遇到问题遇到这情况只能寄托于别人的方法了。我自己的项目里就因为用的好多组件年久失修没人管,逼着我download代码直接改来解决。 这也算是开源的一个恼人的小问题吧

lsjwzh commented 7 years ago

@Kongdy @ShinonomeHana 按照View体系本身的情况,是不应该暴露出拦截方法的。使用继承复写的方式似乎更好。 不过要不先发个PullReqeust看看哈。