Android 滚动整个屏幕而不是仅滚动列表视图

Android scroll whole screen instead of only listview

我有以下布局结构:

RelativeLayout
  -LinearLayout(Vertical)
  |  ...
  |  ...
  -LinearLayout(Vertical)
     ListView

ListView 有一堆由 ArrayAdapter 设置的项目。目前,只有 ListView 是可滚动的,第一个 LinearLayout 留在原处。但是,我希望整个屏幕都可以滚动,所以如果用户滚动得足够远,如果有足够的列表项,ListView 可能会占据整个屏幕。

此图说明了所需的行为(滚动前后) 红框是第一个LinearLayout,绿框是LinearLayoutListView

感谢您宝贵的帮助!

如果您不必使用 RelativeLayout,您可以尝试使用 CoordinatorLayout 的不同结构,如下所示:

<CoordinatorLayout >
    <AppBarLayout >
        <CollapsingToolbarLayout >
             <!-- first layout with the property layout_scrollFlags="scroll" -->
        </CollapsingToolbarLayout >
    </AppBarLayout >

    <ListView > <!-- or RecyclerView to be more updated -->
</CoordinatorLayout >

如果您必须使用 RelativeLayout,您可以选择在 Scrollview 中实现全部(性能不佳并重新发明轮子)或者您可以将视图添加为列表视图的 header

-----为清楚起见编辑这里是我的布局

<android.support.design.widget.CoordinatorLayout
    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:fitsSystemWindows="true"
    tools:context="it.italia.playground.CollapseActivity">

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

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                android:padding="@dimen/padding16"
                app:layout_collapseMode="parallax">

                <ImageView
                    android:id="@+id/image"
                    android:layout_width="150dp"
                    android:layout_height="150dp"
                    android:layout_alignParentTop="true"
                    android:layout_centerInParent="true"
                    android:maxHeight="@dimen/padding16"
                    android:scaleType="centerCrop"
                    android:src="@drawable/img"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/image"
                    android:layout_centerInParent="true"
                    android:layout_marginTop="@dimen/padding16"
                    android:text="text title"
                    />
            </RelativeLayout>


            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

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

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

    <include layout="@layout/content_layout"></include>


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

使用适合屏幕的滚动布局并使列表视图包裹内容

正如 wolfy 所说,CoordinatorLayout 是最好的选择,但 ListView 在那种情况下不起作用,因为它没有实现与 [=10= 通信所需的正确回调接口]. CoordinatorLayout 实际上如何协调其子视图的滚动? 您需要为实现 NestedScrollingChild 接口的视图切换 ListView,您实际上不需要为这些方法编写代码,例如 RecyclerViewSwipeRefreshLayout 为您完成这项工作 ;)

然后 CoordinatorLayout 实现了 NestedScrollingParent 接口,这为您节省了另一份工作(google 文档):

This interface should be implemented by ViewGroup subclasses that wish to support scrolling operations delegated by a nested child view.

如果您需要滑动刷新操作,SwipeRefreshLayout 实现了这两个接口。查看视图层次结构,它位于 CoordinatorLayoutRecyclerView 之间,因此它可以同时处理 NestedScrollingChildNestedScrollingParent

底线:为 RecyclerView 切换 ListView 或使 ListView 实现 NestedScrollingChild。它应该以任何方式工作!

关于处理新 APi 的滚动的两个极好的解释:

https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout

https://lab.getbase.com/nested-scrolling-with-coordinatorlayout-on-android/

代码 sample,用于实现演示中的 NestedScrollingChild

您可以使用 RecyclerView 而不是 ListView,然后您可以将列表包装在 NestedScrollView 中并调用 ViewCompat.setNestedScrollingEnabled(recyclerView, false)。在顶部,您可以使用另一个 ScrollView 包含所有内容( 红色标记的视图 在您的图形中)并将那个 NestedScrollView 绿色标记的列表)小时候在里面。

NestedScrollView负责动态设置高度,否则recyclerView只会使用一个固定高度。请注意,如果列表太长,它可能会出现不需要的 UI 滞后,那么通过在列表中展开不同的布局,将所有内容设置为适配器中列表的一部分会更有效。另一方面,这也可能有点棘手,因为整个布局现在是列表的一部分,并且对其所做的所有更改都需要通过适配器。

这是解决方案:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:fitsSystemWindows="true">

    <!--here if you want a fab-->
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/add_edu_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="@dimen/dim_16dp"
        android:layout_marginEnd="@dimen/dim_16dp"
        app:srcCompat="@drawable/ic_plus_24dp" />


     <!--starting the scroll of the layout-->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!--scroll view-->
        <RelativeLayout
            android:id="@+id/mainScrollChild"
            android:layout_width="match_parent"
            android:layout_height="0dp">

            <!--start adding your red part-->
            <android.support.v7.widget.CardView
                android:id="@+id/cardView"
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:layout_margin="8dp"
                android:padding="1dp"/>                    

            <!--end Red Part-->

            <!--start the green part (recyclerView)-->
            <RelativeLayout
                android:id="@+id/rel2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/cardView">

                <android.support.v4.widget.NestedScrollView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

                    <android.support.v7.widget.RecyclerView
                        android:id="@+id/recyclerView"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content" />
                </android.support.v4.widget.NestedScrollView>
            </RelativeLayout>
            <!--end green part-->
        </RelativeLayout>
    </ScrollView>
</RelativeLayout>

输出: