Change column span count of StaggeredGridLayout dynamically based on item position

2.5k views Asked by At

I would like to achieve this layout for (n) items list: this layout

So far now I'm able to display the items in two columns but how can I merge two columns in one for specific position (i.e as item 7)?

I have tried many solution provided at SO and also other but none of them worked for me. The solutions provided there were either using LinearLayout inflating static layouts or were providing solution for partition with in the columns.

I've also tried using setSpanLookup method but no luck..

3

There are 3 answers

0
Muahmmad Tayyib On BEST ANSWER

Finally the solution that worked for me after exhaustive struggle is here:

    @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);
        }

Hope this will help u also.

0
Kevin On

As you said, setSpanLookup is the best method, I think.

Try this code:

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)
    }
}

You need to know the value getSpanSize returned means weight, not column count.

In terms of item layout, you can use different ViewHolder in special position.

For example:

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
}
0
alan On

Just create a table : In your case is is 8 rows and 3 columns, set the borderline and border alignment, item 7 and 14 will take 3 cells. Here an example :

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);
}