根据另一个 RV 滚动增加和减少 RV 高度

increasing and decreasing RV height depending on another RV scrolling

我想实现以下行为 -

https://ezgif.com/optimize/ezgif-6-66c61806b01c.gif

这是我的 XML 文件 -

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/fragment_marketplace_root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="7dp">

    <LinearLayout
        android:id="@+id/fragment_marketplace_main_linear_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusableInTouchMode="true"
        android:orientation="vertical">

        <com.twoverte.views.ClearableAutoCompleteTextView
            android:id="@+id/fragment_marketplace_searchview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="14dp"
            android:layout_marginTop="15dp"
            android:layout_marginEnd="14dp"
            android:completionThreshold="0"
            android:hint="@string/fragment_marketplace_search_hint"
            android:iconifiedByDefault="false"
            android:inputType="text|textAutoCorrect"
            android:maxLength="25"
            android:textIsSelectable="false"
            android:textSelectHandle="@xml/empty_shape"
            tools:layout_editor_absoluteX="1dp"
            tools:layout_editor_absoluteY="1dp" />

        <TextView
            android:id="@+id/fragment_marketplace_discover_products_from_myverte_textview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="14dp"
            android:layout_marginTop="15dp"
            android:fontFamily="@font/noto_sans"
            android:text="@string/fragment_marketplace_discover_products_from_myverte"
            android:textSize="17sp" />

        <androidx.core.widget.NestedScrollView
            android:id="@+id/fragment_marketplace_vendors_nested_scrollview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/fragment_marketplace_vendors_recycler_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="14dp"
                android:layout_marginEnd="14dp"
                android:orientation="horizontal"
                tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
                tools:listitem="@layout/fragment_marketplace_vendor_row_item" />

        </androidx.core.widget.NestedScrollView>


        <androidx.core.widget.NestedScrollView
            android:id="@+id/fragment_marketplace_featured_products_nested_scroll_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/fragment_marketplace_featured_products_textview"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/very_light_grey"
                    android:fontFamily="@font/noto_sans"
                    android:paddingStart="14dp"
                    android:paddingLeft="14dp"
                    android:paddingTop="15dp"
                    android:paddingEnd="14dp"
                    android:text="@string/fragment_marketplace_featured_products"
                    android:textSize="17sp"
                    android:visibility="gone"
                    tools:visibility="visible" />

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/fragment_marketplace_products_recycler_view"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="center"
                    android:background="@color/very_light_grey"
                    app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
                    tools:listitem="@layout/fragment_marketplace_products_row_item" />

                <View
                    android:id="@+id/activity_product_page_bottom_view"
                    android:layout_width="match_parent"
                    android:layout_height="70dp"
                    android:layout_marginTop="60dp"
                    android:background="@color/light_black"
                    android:visibility="gone"
                    tools:visibility="visible" />


            </LinearLayout>

        </androidx.core.widget.NestedScrollView>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

我已经尝试了很多 setOnScrollChangeListeneraddOnScrollListener 的组合,但没有像预期的那样工作。

所需的结果是能够将最高 RV 增加和减少到一个上限。

向下滚动底部RV时应减少,向上滚动时应增加。

如果有人能帮我解决这个问题,我真的会亲吻他的腿,我花了很多时间试图破解如何让我厌倦这种行为。

编辑

所需的动画 -

我终于想通了。我将首先分享 XML 文件的代码,然后再解释所有相关内容。

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:minHeight="132dp"
            android:fitsSystemWindows="true"
            app:titleEnabled="false"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <View
                android:id="@+id/blue_view"
                android:layout_width="match_parent"
                android:layout_height="128dp"
                android:background="@android:color/holo_blue_bright"
                app:layout_collapseMode="pin"
                app:layout_collapseParallaxMultiplier="0"
                android:layout_gravity="top"/>

            <HorizontalScrollView
                android:id="@+id/pink_view"
                android:layout_width="match_parent"
                android:layout_height="128dp"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="1"
                android:layout_gravity="bottom">

                <View
                    android:layout_width="2000dp"
                    android:minWidth="2000dp"
                    android:layout_height="match_parent"
                    android:background="@color/colorAccent"/>

            </HorizontalScrollView>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Note: I used View with different colors in order to preview different segments in the Layout. I also used HorizontalScrollView in order to showcase something like a RecyclerView as in the gif you uploaded.


好的,首先,我们需要创建一个 CollapsingToolbarLayoutlayout_scrollFlags

  • 我们使用 scroll 必须启用标志才能使任何滚动效果生效
  • 我们使用 snap 标志来确定当视图仅被部分缩小时要做什么。如果滚动结束并且视图大小已减小到其原始大小的 50% 以下,则此视图将 return 变为其原始大小。如果尺寸大于其尺寸的 50%,它将完全消失。
  • 我们使用 exitUntilCollapsedminHeight 来将 Toolbar 折叠成指定的 minHeight

我们希望 CollapsingToolbarLayout 具有:

  • layout_height 设置为 Toolbar
  • expanded 高度
  • minHeight 设置为 Toolbar
  • collapsed 高度

In this case, since we want the HorizontalScrollView (pink_view) only to get smaller in height, we set the minHeight to the [ height of blue_view + smaller height of pink_view ]

Therefore, since blue_view will remain 128dp and we want pink_view to go down to 4dp, we set the minHeight to 132dp.

 

So here is a small example. Assume the blue_view is like 100dp and the pink_view is initially 100dp. So that's how we want it to show at first, but when I start scrolling we want the pink_view to go down to 20dp and the blue_view will stay at 100dp.

Therefore, layout_height will be 200dp and the minHeight will be 120dp.


现在,我们希望 HorizontalScrollViewpink_view 折叠成 CollapsingToolbarLayout 高度

因此,我们将 layout_collapseMode="parallax" 添加到 pink_view 以便它与 CollapsingToolbarLayout 一起滚动。

layout_collapseParallaxMultiplier 决定图像的哪一部分(百分比)将隐藏在底部内容之下。在这里,我们希望它 all 被隐藏。因此,我们设置为1.


与此同时,我们希望 blue_view 保持 固定 到顶部。而且我们也不希望它隐藏在任何底部内容下。

所以,我们将 layout_collapseMode="pin" 添加到 blue_view,这样它就固定在 CollapsingToolbarLayout 的顶部。

我们还添加了 layout_collapseParallaxMultiplier="0" 以使其不被任何内容隐藏。


Please note that if the heights of the elements exceeds the minHeight, the CollapsingToolbarLayout will be pushed above the screen. It will then seem as if the height of the top item (here blue_view) is decreasing in size.


预览:


这是另一个带有 RecyclerView:

的演示

上面 RecyclerView 演示的 XML 如果有人感兴趣,请看下面。

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:minHeight="148dp"
            android:fitsSystemWindows="true"
            app:titleEnabled="false"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <View
                android:layout_width="match_parent"
                android:layout_height="128dp"
                android:background="@android:color/holo_blue_bright"
                app:layout_collapseMode="pin"
                app:layout_collapseParallaxMultiplier="0"
                android:layout_gravity="top"/>

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/hv_list"
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="128dp"
                android:minHeight="20dp"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="1"
                android:layout_gravity="bottom"/>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

编辑:RecyclerViews 和 ViewHolders 的重要事项

要实现 RecyclerViewViewHolder 高度 调整大小,我们必须在 offset 的 [=74] 时调整它们的大小=] 滚动变化。

This is because the CollapsingToolbarLayout just scrolls the elements inside it under each other instead of actually resizing them.

因此,我们必须使用此处称为 hv_listRecyclerView 和此处称为 app_barAppBarLayout

val hv_list: RecyclerView = findViewById(R.id.hv_list)

val app_bar: AppBarLayout = findViewById(R.id.app_bar)

之后,我们需要记住hv_list的原始大小。

val hv_original_height: Int = hv_list.layoutParams.height

最后,我们需要为AppBarLayout设置一个OffsetChangedListener。在那里,我们将更改 RecyclerViewheight,然后给它一个 margin bottom 以将其向上推 只因为它有重力底

app_bar.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
    override fun onOffsetChanged(appBarLayout: AppBarLayout, i: Int) {
        hv_list.updateLayoutParams {
            this.height = hv_original_height + i
            (this as CollapsingToolbarLayout.LayoutParams).setMargins(0, 0, 0, abs(i))
        }
    }
})

Make sure that your itemView in the RecyclerView has height of match_parent