复杂布局SwipeRefreshLayout+TabLayout+NestedScrollView+RecyclerView冲突

复杂布局SwipeRefreshLayout+NestedScrollView+ViewPager+TabLayout
引起滑动冲突

今天做了项目的时候遇到一个布局比较复杂的界面。
最外层是一个SwipeRefreshLayout
然后包裹了一个CoordinatorLayout
其中又使用到了可折叠的AppBarLayout
以及NestedScrollView和ViewPager

总体的布局是这样子的

<SwipeRefreshLayout>
    <CoordinatorLayout>
        <AppBarLayout>
            <轮播图/>
            <分类/>
            <CollapsingToolbarLayout>
                <TabLayout/>
            CollapsingToolbarLayout>
        AppBarLayout>
        <NestedScrollView>
            <ViewPager/>
        NestedScrollView>
    CoordinatorLayout>
SwipeRefreshLayout>

其中Viewpager有嵌套了两个带有RecyclerView的Fragment

首先是RecyclerView和NestedScrollViewd 冲突


首先是RecyclerView和NestedScrollViewd 冲突,造成滑动不流畅的问题

这个比较简单,设置RecyclerView.setNestedScrollingEnabled(false);
就可以解决。

然后是SwipeRefreshLayout和NestedScrollView刷新的问题

SwipeRefreshLayout中嵌套了NestedScrollView会导致滑动NestedScrollView的时候激活SwipeRefreshLayout
解决办法是通过监听滑动是否到顶部,具体代码如下:

NestedScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                    SwipeRefreshLayout.setEnabled
                    (NestedScrollView.getScrollY() == 0);
            }
        });

最后就是一个TabLayout和SwipeRefreshLayout还有NestedScrollView组合使用的问题了

因为是嵌套了CoordinatorLayout,AppBarLayout和CollapsingToolbarLayout形成一个可以折叠的功能,
顶部的轮播图和分类可以折叠起来,而TabLayout与ViewPager结合,
其中ViewPager由包括了RecyclerView

然后问题就来了

首先,当你滑动Viewpager中的RecyclerView后,界面会往下滑动,直到TabLayout固定在顶部,
然后滑动事件转移到RecyclerView开始下滑,这一切都是正常的,
但是当你往回滑动的时候问题就出现了,因为TabLayout固定在顶部,
当RecyclerView往回滑动到最上后按照理想的状态,
下一个动作是轮播图开始从这点状态变为展开,但是APP会以为你已经滑到顶部了,
而实际上顶部折叠起来的轮播图还未展开,这时候你继续下滑就会唤出SwipeRefreshLayout
这并不是我们想要的效果,一些帖子之后,发现appBarLayout中带有一个监听事件addOnOffsetChangedListener能够监听折叠和非折叠的距离
那么,刚才的代码就需要修改一下,变成下面这样,通过判断AppBarLayout和NestedScrollView是否都已到达顶部。

appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (!binding.refreshFind.isRefreshing()) {    //如果不在刷新状态
                    //判断是否滑动到最顶部
                    binding.refreshFind
                            .setEnabled(binding.scrollviewFins.getScrollY() == verticalOffset);
                }
            }
        });

自己记录一下,原创文章,转载请注明出处

你可能感兴趣的:(Android日常)