Объединение нескольких столбцов с помощью RecyclerView

Итак, я пытаюсь использовать шахматный макет, но первый элемент в списке должен занимать два столбца. Первые два ряда также имеют фиксированную высоту. У меня все работает, кроме первого элемента, охватывающего два столбца.

Я использую RecyclerView.Adapter с StaggeredGridLayoutManager. Не похоже, что это нестандартная функциональность. Я предполагаю, что могу создать собственный менеджер компоновки. Я просто не знаю, с чего начать. Я пробовал искать, но ничего не могу найти о том, как заставить элементы охватывать несколько столбцов.

Изображение ниже — это то, что я ищу в списке.

Разметка в шахматном порядке


person DDukesterman    schedule 11.12.2014    source источник
comment
Вы когда-нибудь находили способ добиться этого?   -  person Jon W    schedule 10.04.2015
comment
Первый элемент всегда занимает два столбца. Мне пришлось поставить отрицательное правое поле, чтобы получить результаты. Второй элемент — это фиктивный элемент с видимостью, установленной на INVISIBLE.   -  person DDukesterman    schedule 29.04.2015
comment
Возможно ли, что вы поделитесь своим кодом об этом решении? Я пытаюсь добиться того же результата, но безуспешно.   -  person MHogge    schedule 08.05.2015
comment
@DDukesterman помог тебе мой ответ? Если да, не могли бы вы принять его? Спасибо.   -  person mato    schedule 16.05.2015
comment
Привет, не могли бы вы опубликовать свой код адаптера, у меня возникла небольшая проблема.   -  person RobinHood    schedule 20.01.2016
comment
Удачи с реализацией? Ищу аналогичную реализацию.   -  person Debjit    schedule 05.02.2018


Ответы (3)


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

Если вы все же хотите распределить их по всем столбцам, вы должны сделать это в реализации адаптера:

public final void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {

    StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
    layoutParams.setFullSpan(true);
}

ИМХО, StaggeredGridLayoutManager все еще находится в стадии интенсивной разработки, и Google хочет, чтобы мы использовали его для обратной связи :(

person mato    schedule 15.12.2014
comment
при попытке сделать это - getLayoutParams возвращает значение null. Кому-нибудь повезло? - person Jason Van Anden; 17.07.2015
comment
@JasonVanAnden, getLayoutParams также возвращал мне значение null. Может быть, мой ответ поможет вам. - person ljmelgui; 25.08.2015
comment
Хммм, этого не должно происходить во время вызова onBindViewHolder... Возможно, у вас есть другая проблема где-то еще, и вы просто решаете ее. - person mato; 27.08.2015
comment
Значит, это невозможно сделать с помощью GridLayoutManager? - person android developer; 16.11.2015
comment
Не совсем «в стадии интенсивной разработки», поскольку StaggeredGridLayoutManager, по-видимому, практически не изменился более года спустя. - person Jozua; 29.03.2016
comment
java.lang.ClassCastException: android.support.v7.widget.RecyclerView$i нельзя преобразовать в android.support.v7.widget.StaggeredGridLayoutManager - person ; 30.07.2018

Что я сделал, чтобы охватить все столбцы для вертикально сконфигурированного макета, так это создал новый LayoutParams и установил для полного диапазона значение true в реализации адаптера:

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position) {

    StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    layoutParams.setFullSpan(true);
    viewHolder.itemView.setLayoutParams(layoutParams);
}
person ljmelgui    schedule 25.08.2015

Решение, предложенное ljmelgui, отлично работает, но его можно смешивать с mato ответьте на небольшую оптимизацию, попытавшись повторно использовать layoutParams, если они существуют:

public final void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {

    StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
    if ( layoutParams == null ) {
          layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    }
    layoutParams.setFullSpan(true);
    viewHolder.itemView.setLayoutParams(layoutParams);
}
person Sebastián    schedule 19.11.2020