Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有两个问题 #21

Open
1181631922 opened this issue Aug 20, 2020 · 5 comments
Open

有两个问题 #21

1181631922 opened this issue Aug 20, 2020 · 5 comments

Comments

@1181631922
Copy link

rt
1.向上滑动列表时初次滑动会有卡顿问题
2.当下方Recyclerview全部显示的时候,在快速fling的过程中,底部Recyclerview在未全部显示(滑动到顶部时)就已经将手势交给外层列表开始滑动头部Recyclerview

@1181631922
Copy link
Author

第一个是因为创建新视图的原因,可以放在子线程。
第二个是因为父控件的onInterceptTouchEvent拦截出的问题,定位原因在Recyclerview里面
// Clear the active onInterceptTouchListener. None should be set at this time, and if one // is, it's because some other code didn't follow the standard contract. mInterceptingOnItemTouchListener = null; if (findInterceptingOnItemTouchListener(e)) { cancelScroll(); return true; }
这里面手动设置为true了,需要自己判断子控件是否滑动到顶部,否则父控件不做拦截,两个问题都已解决

@1181631922
Copy link
Author

第二个问题有两种解决方法:
一:子控件通知父控件不要干涉我的手势事件:

@Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        /*
        通知父view是否可以截获事件
         */
        final boolean isScrollUp = !canScrollVertically(-1);
        if (isScrollUp) {
            /*
            同父的此重写方法return super.onInterceptTouchEvent(v)
             */
            getParent().requestDisallowInterceptTouchEvent(false);
            Log.d("子dispatchTouchEvent", "子滑动到顶部");
        } else {
            Log.d("子dispatchTouchEvent", "子没有滑动到顶部,可以继续向上滑动");
            /*
            同父的此重写方法的return false
             */
            getParent().requestDisallowInterceptTouchEvent(true);
        }
        return super.onInterceptTouchEvent(e);
    }

二:父控件中直接去不拦截

@Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        final boolean intercept = super.onInterceptTouchEvent(e);

        if (e != null) {
            final int action = e.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN: {
                    Log.d("父dispatchTouchEvent", "ACTION_DOWN");
                }
                case MotionEvent.ACTION_MOVE: {
                    Log.d("父dispatchTouchEvent", "ACTION_MOVE");
                }
                case MotionEvent.ACTION_CANCEL: {
                    Log.d("父dispatchTouchEvent", "ACTION_CANCEL");
                }
                case MotionEvent.ACTION_UP: {
                    Log.d("父dispatchTouchEvent", "ACTION_UP");
                }
            }
        }
        RecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
        if (childRecyclerView != null) {
            boolean isScrollUp = !childRecyclerView.canScrollVertically(-1);
            if (isScrollUp) {
                Log.d("父dispatchTouchEvent", "子滑动到顶部");
            } else {
                Log.d("父dispatchTouchEvent", "子没有滑动到顶部,可以继续向上滑动");
                return false;
            }
        }
        if (intercept) {
            Log.d("父dispatchTouchEvent", "父控件拦截手势了");
        } else {
            Log.d("父dispatchTouchEvent", "父控件未拦截手势");
        }
        return intercept;
    }

@1181631922
Copy link
Author

上面两种方法有bug,第二种方法暂时废弃,第一种方法需要加上判断,如下,否则viewpager划不动
如下:

    private var oldX = 0F
    private var oldY = 0F

    private var newX = 0F
    private var newY = 0F

    override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
        val intercept = super.onInterceptTouchEvent(e)
        if (e != null) {
            val action = e.action
            when (action) {
                MotionEvent.ACTION_DOWN -> run {
                    oldX = e.x
                    oldY = e.y
                    Log.d("dispatchTouchEvent", "parent ACTION_DOWN")
                }
                MotionEvent.ACTION_MOVE -> run {
                    newX = e.x
                    newY = e.y
                    Log.d(
                        "onInterceptTouchEvent",
                        "onInterceptTouchEvent parent oldX:" + oldX + ",oldY:" + oldY
                    )
                    Log.d(
                        "onInterceptTouchEvent",
                        "onInterceptTouchEvent parent newX:" + newX + ",newY:" + newY
                    )
                    oldX = newX
                    oldY = newY
                }
                MotionEvent.ACTION_CANCEL -> run {
                    Log.d("dispatchTouchEvent", "parent ACTION_CANCEL")
                }
                MotionEvent.ACTION_UP -> run {
                    Log.d("dispatchTouchEvent", "parent ACTION_UP")
                }
            }
        }
        val childRecyclerView: RecyclerView? = findNestedScrollingChildRecyclerView()
        if (childRecyclerView != null) {
            val isScrollUp = !childRecyclerView.canScrollVertically(-1)
            if (isScrollUp) {
                Log.d("dispatchTouchEvent", "parent 子滑动到顶部")
            } else {
                Log.d("dispatchTouchEvent", "parent 子没有滑动到顶部,可以继续向上滑动")
                /*
                不再这里去处理手势了,放在子中,不用去查询view,提高效率
                如果x轴偏移量大于y轴此时父控件先去处理,之后再交给子控件
                 */
                return if (abs(newX - oldX) > abs(newY - oldY)) {
                    intercept
                } else {
                    false
                }
            }
        }
        if (intercept) {
            Log.d("dispatchTouchEvent", "parent 父控件拦截手势了")
        } else {
            Log.d("dispatchTouchEvent", "parent 父控件未拦截手势")
        }
        return intercept
    }

@trycatchx
Copy link

第二种方法暂时废弃,第一种方法需要加上判断

两种方法(外部拦截和 内部拦截)都可以进行加入判断使 ViewPager 滑动。

@1181631922 1181631922 reopened this Jan 18, 2021
@1181631922
Copy link
Author

1181631922 commented Jan 18, 2021

这里还有两个问题,就是三层嵌套滑动的fling还是有问题,等待解决后会提交解决方案
另外一个问题是三层嵌套滑动,如果父Recyclerview滑动到底部,子Recyclerview viewpager切换会有问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants