Search code examples
androidandroid-recyclerviewstaggered-gridview

Setup span in StaggeredGridLayoutManager


I need to create a view like the following (this is an iOS screenshot since I've already created it).

Each blue box is part of a linear layout of a RecyclerView, while each green item is part of a staggered layout.

I'm able to create that structure. The problem is that I cannot make each gray box half of the yellow box. Using the StaggeredGridLayoutManager I'm not able to control the span (size) of the boxes that appear for the inner recycler view. Only a GridLayoutManager has the chance to set a span size lookup.

The desiderata is to calculate the boxes based on the with of the container. For example: if the screen is 99, the yellow box should be 66 while the gray 33.

Do you have any suggestions on how to achieve this?

Here a snippet of the code I'm using:

public class BoxViewAdapter extends RecyclerView.Adapter<BoxViewAdapter.BoxViewHolder> {
    private List<Box> mValues;
    private Context mContext;
    protected BoxViewAdapter.ItemListener mListener;

    public BoxViewAdapter(Context context, List<Box> values, BoxViewAdapter.ItemListener itemListener) {
        mValues = values;
        mContext = context;
        mListener = itemListener;
    }

    @Override
    public BoxViewAdapter.BoxViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.box_view_item, parent, false);
        return new BoxViewAdapter.BoxViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull BoxViewAdapter.BoxViewHolder holder, int position) {
        holder.bind(mValues.get(position));
    }

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

    public interface ItemListener {
        void onItemClick();
    }

    public class BoxViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public Box item;
        private RecyclerView recyclerView;

        public BoxViewHolder(View v) {

            super(v);

            v.setOnClickListener(this);

            StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL);
            recyclerView = v.findViewById(R.id.cardRecyclerView);
            recyclerView.setLayoutManager(staggeredGridLayoutManager);
        }

        public void bind(Box item) {
            this.item = item;
            recyclerView.setAdapter(new CardViewAdapter(itemView.getContext(), item.cards, null));
        }


        @Override
        public void onClick(View view) {
            if (mListener != null) {
                mListener.onItemClick();
            }
        }
    }
}

enter image description here


Solution

  • In the meantime, I've resolved this way.

    In onBindViewHolder of CardViewAdapter I simply set LayoutParams for itemView. Since the item view is the rendered inside a RecyclerView, StaggeredGridLayoutManager knows how to deal with it.

    @Override
    public void onBindViewHolder(@NonNull CardViewHolder viewHolder, int position) {
        if (mUseLayoutParameters) {
            int singleScreenWidth = DisplayUtils.getScreenWidth() / 3;
            Card card = mValues.get(position);
            if (card.isDoubleSized) {
                singleScreenWidth = singleScreenWidth * 2;
            }
    
            StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(singleScreenWidth, ViewGroup.LayoutParams.MATCH_PARENT);
            viewHolder.itemView.setLayoutParams(layoutParams);
        }
    
        viewHolder.bind(mValues.get(position));
    }