Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing layout managers for different views in RecyclerView

I implemented an expandable recyclerview with child elements that are part of the list. I followed this code. This is how it works,

The implementation of ExpandableListView using RecyclerView is briefly described as follows. The list model has an additional parameter "type" that identifies whether the item is a header or child. By checking this parameter, the adapter inflates view and viewholder corresponding to the type. If the type is HEADER, it will inflate the layout of header item, that contains a TextView and a ImageView for indicating whether the child tree is expanded or not.

Now, what I want to do is make the expanded layout a grid. I would normally do this by setting the layout manager to GridLayoutManager but in this case, I am only using one recyclerview, which means that I can't change the layout manager without changing the header which ends up causing the entire recyclerview to turn into a grid including the headers.

My question is: how would you change the layout manager for only a couple layouts inside the adapter?

Edit: I added some code.

Recyclerview adapter:

public class ExpandableListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

// These are constants that are used to determine if the item is a child or a header and is defined with each item from the data model
public static final int HEADER = 0;
public static final int CHILD = 1;

private List<Item> data;

public ExpandableListAdapter(List<Item> data) {
    this.data = data;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) {
    View view = null;

    LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // Check whether the item is a header or child and inflate differnet layouts
    switch (type) {
        case HEADER:
            // Inflate a header layout if the item is a header
            view = inflater.inflate(R.layout.list_header, parent, false);
            ListHeaderViewHolder header = new ListHeaderViewHolder(view);
            return header;
        case CHILD:
            // Inflate a child layout if the item is a child
            view = inflater.inflate(R.layout.list_child, parent, false);
            ListChildViewHolder child = new ListChildViewHolder(view);
            return child;
    }
    return null;
}

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    final Item item = data.get(position);

    // Bind different layouts based on if the item is a header or child
    switch (item.getType()) {
        case HEADER:
            // ...
        case CHILD:
            // ...
    }
}

@Override
public int getItemViewType(int position) {
    return data.get(position).type;
}

@Override
public int getItemCount() {
    return data.size();
}

// Viewholder for the header items
private static class ListHeaderViewHolder extends RecyclerView.ViewHolder {
    // ...
}

// Viewholder for the child items
private static class ListChildViewHolder extends RecyclerView.ViewHolder {
    // ...
}

And this is the main activity where I declare the layout manager:

recyclerview = (RecyclerView) findViewById(R.id.recyclerview);
recyclerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
like image 930
spectre10 Avatar asked May 29 '16 04:05

spectre10


2 Answers

You can change the layout manager to GridLayoutManager and define the "span size" for the header, for example, if you want the grid with 2 columns, the header should have span size 2 and the children span size 1:

    GridLayoutManager glm = new GridLayoutManager(getContext(), 2);
    glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            switch(getTypeForPosition(position)) {
                case HEADER:
                    return 2;
                default:
                    return 1;
            }
        }
    });
    recyclerView.setLayoutManager(glm);

There is a full example of expandable grid with headers here using this library.

like image 183
Gustavo Avatar answered Oct 15 '22 19:10

Gustavo


change the layout manager to gridlayout manager and handle the span size as mentioned below

layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                int type=mAdapter.getItemViewType(position);
                if (type == "view holder type name")
                    return 2;
                else
                    return 1;
            }
        });
like image 43
sonal balekai Avatar answered Oct 15 '22 19:10

sonal balekai