NestedScrollView和CoordinatorLayout. 滚动时的问题

35

我遇到了一个关于CoordinatorLayoutNestedScrollView的奇怪问题(使用设计支持库22.2.0)。

当使用小于NestedScrollView的内容时,我应该有一个固定的内容。 然而,尝试上下滚动内容时,我发现内容被移位,并且再也无法回到原来的位置。

这里是一个简短的示例:enter image description here

以下是代码:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_scrollFlags="scroll|enterAlways" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <FrameLayout
            android:paddingTop="24dp"
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="@dimen/padding">

        </FrameLayout>

    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:visibility="gone"
        android:src="@drawable/ic_done" />

</android.support.design.widget.CoordinatorLayout>

这里有最佳解决方案,请查看:https://dev59.com/-F0Z5IYBdhLWcg3w6jwe#34947835 - Mansukh Ahir
5个回答

37

在详细片段中只保留一张卡片时,这也可以在cheesesquare演示中观察到。

我能够(目前)使用这个类解决这个问题:https://gist.github.com/EmmanuelVinas/c598292f43713c75d18e

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="com.evs.demo.layout.FixedScrollingViewBehavior">
    .....   
</android.support.v4.widget.NestedScrollView>

2
目前的解决方法是一个很好的解决方案。我认为这绝对是支持库中的一个错误。 - Gabriele Mariotti
2
不错的修复。但是,当滚动内容小于滚动本身时,滚动仍然会响应并折叠工具栏。有没有想法只在完全不需要滚动(对于小内容场景)时禁用滚动和折叠呢? - GuillermoMP
@GuillermoMP,你解决了这个问题吗?我也遇到了同样的问题。 - Jerry
在 onMeasure 之后,这个修复方法运行良好。但是,在片段启动后,ViewCompat.isLaidOut(appBar) 始终为 false。例如,在屏幕旋转后,此方法返回 true。我错在哪里了? - VKDev
这是一个演示嵌套滚动视图的示例应用程序,它位于父滚动视图中:https://github.com/AdamSHurwitz/NestedScrolling - AdamHurwitz
app:layout_behavior= 不让我输入类名。你是如何输入这个类的? - chari sharma

37

我认为这不是支持库中的一个bug,只需使用此方法即可。

<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    android:layout_gravity="fill_vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

我已经尝试了上面的解决方法,效果非常好。你也可以试试! - datienza
实际上,这确实有效!至少在22.2.1版本上是这样的。对我来说,不需要使用fillViewPort - Pin
4
我刚刚添加了'android:layout_gravity="fill_vertical"',它奏效了。谢谢@LiFei。 - Suresh Kumar
这是问题的正确答案。NestedScrollView中没有错误,上面使用的类是不必要的。 - Yash Sampat
2
在我的情况下,这绝对行不通,因为在嵌套的滚动视图中有一个带有内部RecyclerView的片段。如果我使用这种方法,RecyclerView可以滚动,但是应用栏不再折叠。 - Neal Sanche
我需要fillViewport...不确定为什么。 - kenyee

5

android:layout_gravity="fill_vertical" 对我也有效。


(注:本翻译保留了原文中的HTML标签)

3
我可能回答晚了,但还是要说一下。 我之前也遇到过类似的问题,但上面提到的解决方法都没能帮到我。 最终,我通过使用支持库的 23 版本来解决了这个问题。
...
compileSdkVersion 23
...
targetSdkVersion 23
...
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:design:23.1.0'

出于兴趣,切换到支持库的v23后,我的构建出现了问题,SDK声称我没有使用Theme.AppCompat,尽管我确实使用了。 - Richard Le Mesurier
我也遇到了v23与Apache弃用库的问题,但这是另一个问题了。一旦解决了这个问题,请尝试查看是否已解决本问题。 - Aleks Nine

2

在布局过程中,onMeasureChild()方法会被多次调用。显然,在此过程中尽早获得子视图的非零高度是关键。在以下情况中,ScrollingViewBehavior未能做到这一点:

int scrollRange = appBar.getTotalScrollRange();
int height = parent.getHeight() 
             - appBar.getMeasuredHeight()
             + scrollRange;

FixedScrollingviewBehavior通过以下方式解决了这个问题:
int height = parent.getHeight() 
             - appBar.getMeasuredHeight() 
             + Math.min(scrollRange, parent.getHeight() - heightUsed);

在很早的时候,将高度值设置为-128,这是应用栏的高度。

一种接近原始代码的替代方案如下:

int height = parent.getMeasuredHeight()
             - appBar.getMeasuredHeight()
             + scrollRange;

请您能否解释一下?作为一个初学者,我发现很难理解。我尝试阅读ScrollingViewBehavior类及其基类HeaderScrollingViewBehavior,但是我无法理解它的意义。 - Kathir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接