NestedScrolling在BottomSheetDialog

时间:2017-01-02 09:34:07

标签: android android-fragments scroll android-viewpager android-nestedscrollview

简短版:

如何设置具有多个此类孩子的NestedScrollingChild的{​​{1}}。

长版

我实施了NestedScrollingParent,其布局由BottomSheetDialogFragment组成,此viewpager的适配器包含ViewPager

现在问题是,因为RecyclerView,在这段时间底部的协调器布局只支持一个直接 NestedScrollingParent,只有适配器的第一个片段可以嵌套滚动。

我的意思是,只要在viewpager上调用NestedScrollingChild,第一项就支持嵌套滚动。但是在我更改页面后,新页面现在不会滚动。然后当我回到上一页时,它仍然支持滚动。

另外,我注意到如果可以滚动的片段或页面被破坏,则后续页面现在可以滚动,这意味着后一页面成为底部工作表的滚动子页面。问题是,现在获得滚动功能的页面不是当前项目而是前一项目(我的适配器必须维护3个片段)。

摘要:

setAdapter之后

  • 片段0可以滚动
  • 然后在将页面更改为片段1后,片段1无法滚动
  • 但切换到片段2,然后返回片段1允许片段1滚动(因为片段0被破坏我猜)

7 个答案:

答案 0 :(得分:1)

在深入研究源代码后,我发现问题在于找到底层NestedScrollingChild时使用的错误算法(谷歌的人没有考虑ViewPager的可能性在底层内。)

请参阅此处的方法:findScrollingChild()

这个方法的作用是返回它在给定视图(本例中为底层)上遇到的第一个NestedScrollingChild,如果是一个有3页的viewpager,则是当前页面之前的那个。此外,此方法在底部CoordinatorLayout包装的子项的布局阶段触发。

考虑到这一点,人们可以设计出许多解决方案,包括对行为本身进行子类化。

此外,可以通过添加和删除此类子项的一个实例(从旧页面中删除,然后添加到当前页面)来限制viewpager中的NestedScrollingChild,这就是我所做的。您可以在适配器的setPrimaryItem内或OnPageChangeListener内执行此操作。务必在底部的协调器布局上调用requestLayout。 (此解决方案取决于寻呼机适配器的布局/结构类型,因此我不会发布我的确切解决方案。)

答案 1 :(得分:1)

这些先前的回复让我有些麻烦。 实际上,在我的情况下,@NonNull Object object中的setPrimaryItem返回一个片段,并且不能转换为NestedScrollView

这是我的XML中的内容:

  • 一个包含BottomSheet的{​​{1}}。
  • ViewPager,其中两页各包含一个ViewPager
  • 每个Fragment在根视图中包含一个Fragment

这是我的NestedScrollView(科特琳)

ViewPagerAdapter

答案 2 :(得分:0)

我也遇到了这个问题,尝试在BottomSheetDialog中使用几乎每个页面都有滚动视图的ViewPager。 我发现这个解决方案由laenger([https://github.com/laenger/ViewPagerBottomSheet][1])制作,并采用它,因此它适合BottomSheetDialog。 希望它可以帮助一些遇到同样问题的人:)

答案 3 :(得分:0)

我有完全相同的问题,并找出非常相似的解决方案 提供我的解决方案供参考:

ViewPagerAdapter.java

....
@Override
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
    super.setPrimaryItem(container, position, object);
    NestedScrollView current = ((NestedScrollView)object);
    current.setNestedScrollingEnabled(true);

    for (int i = 0; i < getCount(); i++) {
        if (i != position) {
            NestedScrollView otherScrollView = container.findViewWithTag(i);
            otherScrollView.setNestedScrollingEnabled(false);
        }
    }

    container.requestLayout();
}
...

另外,我写了一篇关于这个主题的博文:Here

答案 4 :(得分:0)

我稍微简化了saiday's解决方案。重要的是要知道我要返回ViewBindings而不是来自instantiateItem的视图。

public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
    super.setPrimaryItem(container, position, object);
    for (int i = 0; i < container.getChildCount(); i++) {
        //First disable nested scrolling for all instantiated child views
        ((NestedScrollView)container.getChildAt(i)).setNestedScrollingEnabled(false);
    }

    //Enable nested scrolling for the primary item
    ViewDataBinding binding = (ViewDataBinding) object;
    NestedScrollView current = ((NestedScrollView)binding.getRoot());
    current.setNestedScrollingEnabled(true);

    container.requestLayout();
}

答案 5 :(得分:0)

使用Androidx库时,RecyclerView实现CREATE OR REPLACE FUNCTION nearest_segment_insert() RETURNS trigger AS DECLARE id_temp integer; $BODY$ BEGIN IF OLD.id = NULL THEN select test_route.id into id_temp,ST_Distance(test_route.the_geom,NEW.the_geom) FROM test_route, ORDER BY 2 ASC LIMIT 1; UPDATE SET p.edges_id = r.id, p.the_geom = r.the_geom, p.dist_val = r.distance, r.distance = -1 FROM test_route r, road_block p, WHERE id_temp = r.id ; END IF; RETURN NEW; END; $BODY$ 而不是NestedScrollingChild

NestedScrollView

答案 6 :(得分:0)

除了@saiday的答案外,这些代码对我来说也非常有效( API 21及更高版本);

这是我的XML中的内容:

一个包含ViewPager的BottomSheet。

具有两个页面的ViewPager,每个页面包含一个片段。

每个片段在根视图中都包含一个NestedScrollView。

和我的ViewPagerAdapter代码(java):

@Override
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
    super.setPrimaryItem(container, position, object);

    Fragment currentFragment = (Fragment) object;
    if (currentFragment.getView() != null) {
        for (int i = 0; i < getCount(); i++) {
            ((NestedScrollView) container.getChildAt(i)).setNestedScrollingEnabled(false);
            ((NestedScrollView) container.getChildAt(i)).getChildAt(0).setNestedScrollingEnabled(false); //this is recyclerview's nestedscroll
        }

        NestedScrollView currentNestedScrollView = ((NestedScrollView) currentFragment.getView());
        currentNestedScrollView.setNestedScrollingEnabled(true);
        currentNestedScrollView.getChildAt(0).setNestedScrollingEnabled(true); //this is recyclerview's nestedscroll, I used getChildAt(0) because I have one element in NestedScrollView.

        container.requestLayout();
    }
}

我的第一个和第二个布局(只是ID不同)

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/marketMembersFragmentScrollView"
    android:fillViewport="true">
    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/marketMembersFragmentRecyclerView"/>
</androidx.core.widget.NestedScrollView>