ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: у меня телефон, так что это не проверено
Если вы напишите свой RecyclerView.Adapter
, вы можете переопределить метод привязки для поиска данных "в неправильном порядке ":
Pos0: данные0 -> Pos1: данные 1 -> Pos2: данные 2
Pos3: данные 5 -> Pos4: данные 4 -> Pos5: данные 3
Pos6: данные 6 -> Pos7: данные 7 -> Pos8: данные 8
Pos9: spacer -> Pos10: spacer -> Pos11: Данные 9
Я предполагаю, что вы передаете некоторую коллекцию данных на ваш адаптер; нам также нужно количество столбцов:
class SnakingAdapter(
private val data: SomeCollection<SomeObject>,
private val cols: Int
) : RecyclerView.Adapter<SomeViewHolder> { ... }
Сначала давайте обработаем крайний случай, когда ваш RecyclerView заканчивается на неполной четной строке. Например, если у вас есть 10 элементов данных (максимальный индекс 9), я предполагаю, что вам нужен последний элемент справа (не слева). Мы сделаем это, создав перед ним 2 элемента «распорки»:
private val twoRows = cols * 2 // left > right & right > left
private val remainder = data.count() % twoRows
// If last row is an odd row => no "spacers"
// If last row is complete => no "spacers"
private val needSpacers = remainder > cols
private val paddedCount =
if(needSpacers) (data.count() / twoRows + 1) * twoRows
else data.count()
private val firstSpacerPosition = data.count() / cols * cols
private val spacerPositions =
if(needSpacers) List(paddedCount - data.count()) { firstSpacerPosition + it }
else emptyList<Int>()
override fun getItemCount(): Int = paddedCount
override fun getItemViewType(position: Int): Int =
if(spacerPositions.contains(position)) 2
else 1
override onCreateViewHolder(parent: ViewGroup, viewType: Int) = when(viewType) {
1 => // create a normal item view & ViewHolder
2 => // create a "spacer" item view & ViewHolder
}
Далее нам нужно связать «неправильные» данные для четных строк:
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position Int) {
// If spacer, do nothing
if(spacerPositions.contains(position)) return
// If even row, flip the order of the data
val twoRowPos = position % twoRows
val rowTwomidpoint = cols / 2 + cols // TODO: extract as a field
val altPosition =
if (twoRowPos >= cols) (position - 2 * (twoRowPos - rowTwoMidpoint)) // TODO: correct for odd cols; should fix for even cols
else position
val data = dataSource.get(altPosition)
// bind data to view holder here
}