Mahdi Giveie
Mahdi Giveie

Reputation: 640

RecyclerView and GridLayoutManager: making one cell bigger

I'm trying to make a layout like the image below! the only thing i want is to make the first cell bigger than the others. what I've tried so far is the below code :

        final AdapterFirstPage mAdapter = new AdapterFirstPage(mItems);
    mRecycle.setAdapter(mAdapter);
    final GridLayoutManager mng_layout = new GridLayoutManager(this, 6);
    mng_layout.setSpanSizeLookup( new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            int index = position%2 ;
            switch(index){
               case 0: return 4;
               case 1: return 2;
               case 2: return 2;
               case 3: return 3;
               case 4: return 3;
               default: return -1;
            }

        }
    });
        mRecycle.setLayoutManager(mng_layout);

actually i've played around with spanCount and changed it from 6 to 4 and still I'm not close to the image below! can anyone please help me to achieve this? enter image description here

Upvotes: 1

Views: 2106

Answers (3)

kris larson
kris larson

Reputation: 30985

That is a limitation of GridLayoutManager. For a vertical scroll, items can only extend across columns and vice versa. It makes the layout calculations a lot simpler when you can't extend across both rows and columns.

If you are trying to do something really simple as in your illustration -- only spanning both rows and columns on the very first image -- then what I would suggest is rethinking this so your first three images are on one row. Your second and third images to the right of the large image would actually be part of the same list item.

  • Change your adapter to have a special item that represents the second position; for instance, a list of items that includes the second and third item.

  • Change your adapter to ignore the third item completely. So for adapter position 2 (zero-based) which would normally return the third item, return the fourth item, and so forth. The missing third item has been represented in the list with the second item.

  • Give that special item (the list) a different view type. Create a view that stacks two images vertically. Binding would then involve the second and third item from that list.

Your span count is clearly 3 since you have three columns. The first item has a span size of 2, the second/third combo item has a span size of 1.

Tweak up the margins on your dual view to match the margins from the RecyclerView and you're in business.

Upvotes: 1

Roadblock
Roadblock

Reputation: 2071

You may do this programmatically as follows:

private GridLayout setUpGrid(List<PictureUrlWithStatus> picWithStatusList) {

    if (picWithStatusList == null) { // No Photos present i.e. no Photos are added
        return null;
    }

    GridLayout.LayoutParams gridLayoutParams = new GridLayout.LayoutParams();
    gridLayoutParams.height = LayoutParams.MATCH_PARENT;
    gridLayoutParams.width = LayoutParams.MATCH_PARENT;

    GridLayout gridLayout = new GridLayout(this);
    gridLayout.setLayoutParams(gridLayoutParams);
    gridLayout.removeAllViews();

    int total_gridCount = picWithStatusList.size();
    int column = 3;
    int rowSize = total_gridCount / column;
    gridLayout.setColumnCount(column);

    //(For First Image which occupies 2 rows), If you are drawing less than 3 images, use 2 rows, else setRowCount as the default (rowSize + 1), extra as the first Image occupies 2 rows and still draws only 3 images.
    if (rowSize == 0)
        gridLayout.setRowCount(2);
    else
        gridLayout.setRowCount(rowSize + 1);

    for (int c = 0;/*getcount from  picWithStatusList*/; c++) {
        RelativeLayout.LayoutParams imageLayoutParam = new RelativeLayout.LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        //The ImageView to load image
        ImageView profilePic = new ImageView(this);
        profilePic.setImageDrawable(getResources().getDrawable(
                R.drawable.ic_launcher));
        profilePic.setScaleType(ScaleType.CENTER_CROP);
        profilePic.setLayoutParams(imageLayoutParam);

        RelativeLayout.LayoutParams picstatusLayoutParam = new RelativeLayout.LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        picstatusLayoutParam.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);

        //The View for Text written Below Image
        TextView profilePicStatus = new TextView(this);
        profilePicStatus.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
        profilePicStatus.setGravity(Gravity.CENTER_HORIZONTAL);
        profilePicStatus.setPadding(0, 2, 0, 0);
        profilePicStatus.setLayoutParams(picstatusLayoutParam);

        RelativeLayout.LayoutParams contentLayoutParams = new RelativeLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        contentLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
        RelativeLayout contentLayout = new RelativeLayout(this);
        contentLayout.addView(profilePic);
        contentLayout.addView(profilePicStatus);
        contentLayout.setLayoutParams(contentLayoutParams);

        if (c >= 0) {
            if (c == 0) {
                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                        2 * width / 3, 2 * width / 3);
                GridLayout.LayoutParams param = new GridLayout.LayoutParams(
                        layoutParams);
                param.setGravity(Gravity.CENTER);
                param.columnSpec = GridLayout.spec(c, 2);
                param.rowSpec = GridLayout.spec(0, 2);

                //Load image into profilePic (ImageView), I am assuming you have imageurl in profilePicWithStatus

                //The text written on top of the images.
                profilePicStatus.setText(c + " ");
                contentLayout.setLayoutParams(param);
            } else {
                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                        1 * width / 3, 1 * width / 3);
                GridLayout.LayoutParams param = new GridLayout.LayoutParams(
                        layoutParams);
                param.setGravity(Gravity.CENTER);

                //Load image into profilePic (ImageView), I am assuming you have imageurl in profilePicWithStatus

                //The Text to be written on the top of image with align bottom
                profilePicStatus.setText(c + " ");
                contentLayout.setLayoutParams(param);
            }

        }
        gridLayout.addView(contentLayout);
    }
    return gridLayout;
}

Also,

PictureUrlWithStatus is a class as follows:

private class PictureUrlWithStatus {
    // url is the Picture url and status will be 'Y'/'y' or 'N'/'n'
    String url, status;

    public PictureUrlWithStatus(String pictureUrl, String pictureStatus) {
        this.url = pictureUrl;
        this.status = pictureStatus;
    }
}

This should set you up

Upvotes: 1

Andy.Zhao
Andy.Zhao

Reputation: 258

Your shouldn't use GridLayoutManager if you want achieve different size items.You should implement your own LayoutManager like this.

Upvotes: 0

Related Questions