Search code examples
androidgrid-layoutandroid-gridlayoutgridlayoutmanager

Android grid layout align like GridLayoutManager style


I have the following GridLayout which stores a number of 6 maximum columns :

<androidx.gridlayout.widget.GridLayout
        android:id="@+id/pokemonTeambuilderSpritesLayout"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        app:columnCount="6"
        app:rowCount="1"
        app:useDefaultMargins="true" />

And here I populate it :

  List<Pokemon> pokemonList = pokemonTeam.getPokemonList();
    for (Pokemon pokemon : pokemonList) {
        CircularImageView ivPokemonSprite = new CircularImageView(mContext);
        String pokemonId = pokemon.get_id();
        int pokemonImageId = PokemonUtils.getPokemonSugimoriImageById(pokemonId, mContext);
        Picasso.get().load(pokemonImageId).into(ivPokemonSprite);
        GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(
                GridLayout.spec(GridLayout.UNDEFINED, 1f),
                GridLayout.spec(GridLayout.UNDEFINED, 1f)
        );
        layoutParams.width = 0;
        ivPokemonSprite.setLayoutParams(layoutParams);
        holder.teamSpritesGridLayout.addView(ivPokemonSprite);

    }

My current output with 6 images is this :

enter image description here

With 3 images :

enter image description here

With 2 images:

enter image description here

My desired output would be :

For 6 images:

enter image description here

For 2 images:

enter image description here

For 4 images:

enter image description here

I want it to add them starting from left to right uniform and If the image doesn't have enough space to fit on its own I want it to "collide" with the others instead of letting margin between them (as you can see in the examples). Thats how I see that the GridLayoutManager works . How can I achieve this ?


Solution

  • you can create custom layout for handling your different cases. something like below:

    
     public class PokemonLayout extends FrameLayout {
        private int height;
        private int width;
        private int childWidth;
    
        public PokemonLayout(Context context) {
            this(context, null);
        }
    
        public PokemonLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public PokemonLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public PokemonLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            width = MeasureSpec.getSize(widthMeasureSpec);
            height = Integer.MIN_VALUE;
            childWidth = Integer.MIN_VALUE;
            measureChildren(widthMeasureSpec, heightMeasureSpec);
            int count = getChildCount();
            for (int i = 0; i < count; i++) {
                final View child = getChildAt(i);
                height = Math.max(child.getMeasuredHeight(), height);
                childWidth = Math.max(child.getMeasuredWidth(), childWidth);
            }
            setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        }
    
        @Override
        protected void onLayout(boolean changed, int leftParent, int topParent, int rightParent, int bottomParent) {
            int count = getChildCount();
            boolean overlap = count * childWidth > width;
            int widthOffset = childWidth;
            if(overlap) {
                widthOffset = childWidth - (Math.abs(width - (count * childWidth)) / (count-1));
            }
            for (int i = 0; i < getChildCount(); i++) {
                View child = (View) getChildAt(i);
                child.layout(i*widthOffset,
                        0,(i*widthOffset) + childWidth
                        , child.getMeasuredHeight());
            }
        }
    }
    
    

    For 3 images:

    enter image description here

    For 5 images:

    enter image description here

    UPDATE 1: change onLayout method to positioning children at the center of layout

       @Override
       protected void onLayout(boolean changed, int leftParent, int topParent, int rightParent, int bottomParent) {
           int count = getChildCount();
           boolean overlap = count * childWidth > width;
           int widthOffset = childWidth;
           int startOffest = (width - (count * childWidth)) / 2;
    
           if(overlap) {
               startOffest = 0;
               widthOffset = childWidth - (Math.abs(width - (count * childWidth)) / (count-1));
           }
    
           for (int i = 0; i < getChildCount(); i++) {
               View child = (View) getChildAt(i);
               child.layout(startOffest+ (i*widthOffset),
                       0,(i*widthOffset) + childWidth + startOffest
                       , child.getMeasuredHeight());
           }
       }