Я хотел бы добиться этого макета для списка (n) элементов:

Пока что я могу отображать элементы в двух столбцах, но как я могу объединить два столбца в один для определенной позиции (например, как элемент 7)?
Я пробовал множество решений, представленных в SO, а также другие, но ни одно из них не сработало для меня. Предоставленные там решения либо использовали LinearLayout, раздувающие статические макеты, либо предоставляли решение для разделения в столбцах.
Я также пробовал использовать метод setSpanLookup, но безуспешно..
@MartinMarconcini Я пробовал ваш код и отлично работает ... но посмотрите и на мое решение. Это звучит более оптимально. я думаю.. что вы думаете об этом...
Я вижу это; Я не большой фанат, если честно. Вы касаетесь параметров макета вручную и делегируете ответственность за то, что отображать, вашей активности. Если это работает для вас, это нормально, но я бы не стал полагаться на «представление, прикрепленное к окну», чтобы решить, что/как что-то показать. Я не знаю, может быть, другие видят это и думают, что это нормально; Я бы не подумал об использовании этого метода; это проблема представления. В вашем примере вы помещаете свою бизнес-логику в метод жизненного цикла, который нелегко протестировать, нелегко изменить, нелегко найти или расширить и т. д. /shrug




Как вы сказали, setSpanLookup, я думаю, лучший метод.
Попробуйте этот код:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val layoutManager = GridLayoutManager(this, 2)
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
if (position == 6 || position == 13) return 2
else return 1
}
}
rv.layoutManager = layoutManager
val items = mutableListOf<String>()
for (i in 1..14) {
items.add("item$i")
}
rv.adapter = MyAdapter(items)
}
}
Вам нужно знать, что возвращаемое значение getSpanSize означает вес, а не количество столбцов.
Что касается макета элемента, вы можете использовать разные ViewHolder в специальной позиции.
Например:
companion object{
const val NORMAL = 0
const val WIDE = 1
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
...
if (viewType == WIDE) return WideViewHolder(wideView)
else return NormalViewHolder(normalView)
}
override fun getItemViewType(position: Int): Int {
if (position == 6 || position == 13) {
return WIDE
}
return NORMAL
}
Просто создайте таблицу: В вашем случае это 8 строк и 3 столбца, установите границу и выравнивание границы, пункты 7 и 14 займут 3 ячейки. Вот пример:
private void insertCell(PdfPTable table, String text, int align, int colspan, Font font) {
//create a new cell with the specified Text and Font
PdfPCell cell = new PdfPCell(new Phrase(text.trim(), font));
//set the cell alignment
cell.setHorizontalAlignment(align);
//set the cell column span in case you want to merge two or more cells
cell.setColspan(colspan);
//in case there is no text and you wan to create an empty row
if (text.trim().equalsIgnoreCase("")) {
cell.setMinimumHeight(10f);
}
//add the call to the table
table.addCell(cell);
}
Наконец, решение, которое сработало для меня после изнурительной борьбы, находится здесь:
@Override
public void onViewAttachedToWindow(MyViewHolder holder) {
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
if (lp != null
&& lp instanceof StaggeredGridLayoutManager.LayoutParams
&& (holder.getLayoutPosition() == 6 || holder.getLayoutPosition() == 13)) {
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
p.setFullSpan(true);
}
holder.setIsRecyclable(false);
}
Надеюсь, это поможет и вам.
Предложения в порядке, если вы хотите увидеть «фальшивый рабочий образец», мне пришлось сделать это для сетки с поддержкой рекламы, поэтому я создал прототип здесь. В частности, «Адаптер», который это делает, находится в том же репозитории, здесь. При всем при этом я использовал GridLayout, а не ступенчатую версию.