Recyclerview связывает все представления одновременно

У меня есть вертикальный recyclerview (с GridLayoutManager) внутри другого recyclerview (с LinearLayoutManager). Проблема, с которой я сейчас сталкиваюсь, заключается в том, что внутреннее recyclerview (с GridLayoutManager) связывает все его элементы одновременно, даже представления, которые на данный момент не отображаются на экране (onBindViewHolder() вызывается для всех его элементов).

Чтобы предоставить вам больше информации, в моем файле макета я поставил высоту моего вида ресайклера как wrap_content.

Я думаю, что проблема в том, что есть два вложенных вертикально recyclerviews, когда родительский RV хочет измерить свои дочерние элементы, а дети - это еще один RV, в onMeasure() он вычисляет размер, необходимый для всего RV, а не только которую он хочет привязать на экране.

Любая идея, как это решить?

Вот файл макета для моего внешнего recyclerview:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/component_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</FrameLayout>

И вот код для моего внутреннего recyclerview:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/gutter"
android:paddingBottom="@dimen/gutter">

<TextView
    android:id="@+id/title_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="@dimen/gutter"
    android:textSize="30sp"
    android:textColor="@android:color/white"
    android:fontFamily="sans-serif-thin"/>

<android.support.v7.widget.RecyclerView
    android:id="@+id/my_slider"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

</LinearLayout>

P.S.: Я использую этот делегат адаптера для моего внешнего recyclerview: https://github.com/sockeqwe/AdapterDelegates

Ответ 1

Я думаю, что вложенные recyclerviewes - очень плохая идея. Когда я пытаюсь прокручивать, какой recyclerview должен ответить на scolling, parrent или child.

Вот почему я думаю, что вы ищете ExpandableListView? Это ограничивается только двумя уровнями списков, но похоже, что это сработает для ваших нужд). Он также решает проблему решения проблемы.

Он будет выглядеть примерно так:

введите описание изображения здесь

EDIT: возможны даже вложенные расширения ExpandableListView:

введите описание изображения здесь

EDIT: проверьте this lib для горизонтальной прокрутки

Ответ 2

Это известная ошибка.
Вы не должны ставить RecyclerView внутри другого RecyclerView, потому что RecyclerView предоставляет своим детям бесконечное пространство.
Следовательно, внутренний RecyclerView продолжает измерять, пока набор данных не исчерпан.
Попробуйте установить setAutoMeasureEnabled (false) в false в менеджере компоновки или вы можете решить эту проблему с помощью адаптера оболочки вместо внутреннего вида recycler.

Ответ 3

Первое, что вам нужно знать, это то, что когда вы вставляете прокручиваемые макеты, внутренние из них получат бесконечность высоты, что делает их wrap_content. На самом деле существует относительно простой способ исправить эту проблему. Скажем, у меня было два вложенных RecyclerViews, таких как эти, в этом случае вертикально ориентированные.

<RecyclerView 
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical>
    <View .../>
    <!-- other stuff -->
    <RecyclerView 
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"/>
</RecyclerView>

Внутренний recyclerView здесь будет связывать все его дети немедленно каждый раз, потому что из его положения ваш экран будет иметь бесконечную высоту.

Решение состоит в том, чтобы установить высоту вашего внутреннего recyclerview на какое-то статическое значение, а не на wrap_content или на совпадение с родителем, поскольку любой из них просто заполнит внешний recyclerview одним видом, все из которых будут связаны сразу из-за большого высота. Если вы сделаете высоту внутреннего recyclerview той же, что и высота дисплея, вы должны увидеть, что ваша проблема ушла.

Вот реализация, которая не будет сразу связывать всех детей:

<RecyclerView 
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical>
    <View .../>
    <!-- other stuff -->
    <RecyclerView 
         android:layout_width="match_parent"
         android:layout_height="@dimen/screen_height"
         android:orientation="vertical"/>
</RecyclerView>

Обратите внимание, что layout_height внутреннего RecyclerView теперь является фиксированным значением, вытащенным из файла измерений. Вы сами должны придумать разумную ценность, чтобы положить туда.

Боковое примечание. Чтобы сделать все это и прокрутить для правильной работы, вам может понадобиться играть с параметром: NestedScrollingEnabled в вашем RecyclerViews - существует несколько известных ошибок, связанных с этим, что вам может понадобиться работать вокруг.

i.e.: innerRecyclerView.setHasFixedSize(true); и innerRecyclerView.setNestedScrollingEnabled(false).

Ответ 4

так что происходит здесь, когда вы помещаете scrollview (без фиксированного размера из-за содержимого обертывания) внутри другого scrollview (опять-таки нет фиксированного размера из-за содержимого wrap), оба вложенных вида прокрутки не отображаются.

Итак, существует два решения -

1- Либо вам придется думать об альтернативном решении для вложенных прокруток 2- Вы можете назначить внешнюю ячейку с фиксированной высотой ячейки recyclerview, чтобы внутри вида recycler можно получить фиксированную компоновку для рендеринга.

Ответ 5

Я мог бы решить мою проблему, используя только один Recyclerview, где он имеет макет сетки, и на основе элементов компонента, которые я добавляю в него, я изменяю для него spancount. В основном вместо добавления внутреннего recyclerview я добавляю элементы, которые должны были перейти во внутренний recyclerview, к внешнему recyclerview.