Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto fit according to screen size in grid layout android

I have created a grid containing full of texts. I want the text to auto-fit according to screen size. I have tried the following code,

    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
    int noOfColumns = (int) (dpWidth / 50);
    return noOfColumns;

I want output something like this

image]2

imag2 It doesn't work as per my need. Please help . Thanks in advance.

like image 605
Anusha Avatar asked Sep 11 '16 12:09

Anusha


2 Answers

Here is an implementation of a grid layout that does all the calculations for you. It places all child views in an equally spaced grid with equal margins. It also optimizes the numbers of columns so that not to have all rows as full as possible (for example, 9 child views would fit on 3 rows as 4,4,1, but 3,3,3 looks much better) It's all dynamic, so don't worry about landscape/portrait/phone/tablet/TV


package .......;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/* A labor-saving layout
/  dynamically places all children on an equally-spaced grid.
   All children get the width/height of the largest child - so they all look similar
 */
public class AutoGridLayout extends ViewGroup
{

    private int mMaxHeight;
    private int mMaxWidth;

    public AutoGridLayout(Context context)
    {
        super(context);
    }

    public AutoGridLayout(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

    public AutoGridLayout(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean shouldDelayChildPressedState()
    {
        return false;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int count = getChildCount();

        mMaxHeight = 0;
        mMaxWidth = 0;
        int childState = 0;

        for (int i = 0; i < count; i++)
        {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE)
            {
                measureChild(child, widthMeasureSpec,  heightMeasureSpec);

                mMaxWidth = Math.max(mMaxWidth, child.getMeasuredWidth());
                mMaxHeight = Math.max(mMaxHeight, child.getMeasuredHeight());
            }
        }

        mMaxHeight = Math.max(mMaxHeight, getSuggestedMinimumHeight());
        mMaxWidth = Math.max(mMaxWidth, getSuggestedMinimumWidth());

        setMeasuredDimension(resolveSizeAndState(mMaxWidth, widthMeasureSpec, childState),
                             resolveSizeAndState(mMaxHeight, heightMeasureSpec,
                                                 childState << MEASURED_HEIGHT_STATE_SHIFT));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom)
    {
        final float pxWidth = (right - left + 1);
        final float pxHeight  = (1 + bottom - top);
        final int totalChildCount = getChildCount();
        int count = 0;
        for (int i = 0; i < totalChildCount; i++)
        {
            if (getChildAt(i).getVisibility() != GONE)
                count++;
        }

        final float minSpacing = pxWidth / 20;
        final int maxPossibleColumns = (int) (pxWidth / (mMaxWidth + minSpacing));
        final int rows = (int)Math.ceil((float)count / maxPossibleColumns);
        final int voidsAtLastRow = (rows * maxPossibleColumns - count);
        // distribute the voids to get an even distribution is possible
        final int nColumns = maxPossibleColumns - voidsAtLastRow / rows;

        // equal spaces as margins and between childs (#spaces = #child + 1)
        final int xSpace = (int)Math.max(0,(pxWidth - nColumns * mMaxWidth) / (nColumns + 1));
        final int ySpace = (int)Math.max(0,(pxHeight - rows * mMaxHeight) / (rows + 1));

        int n = 0;
        for (int i = 0; i < totalChildCount; i++)
        {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE)
            {
                final int col = n % nColumns;
                final int x = xSpace + (xSpace + mMaxWidth) * col;

                final int row = n / nColumns;
                final int y = ySpace + (ySpace + mMaxHeight) * row;

                // Place the child.
                child.layout(x, y,x+mMaxWidth,y+mMaxHeight);
                n++;
            }
        }
    }

}

Sample

like image 161
Erez Amir Avatar answered Sep 28 '22 06:09

Erez Amir


Here's a custom implementation of GridLayout that will do what you need: AutoGridLayout

public class AutoGridLayout extends GridLayout {

    private int defaultColumnCount;
    private int columnWidth;

    public AutoGridLayout(Context context) {
        super(context);
        init(null, 0);
    }

    public AutoGridLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public AutoGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr);
    }

    private void init(AttributeSet attrs, int defStyleAttr) {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AutoGridLayout, 0, defStyleAttr);
        try {
            columnWidth = a.getDimensionPixelSize(R.styleable.AutoGridLayout_columnWidth, 0);

            int[] set = { android.R.attr.columnCount /* id 0 */ };
            a = getContext().obtainStyledAttributes(attrs, set, 0, defStyleAttr);
            defaultColumnCount = a.getInt(0, 10);
        } finally {
            a.recycle();
        }

        /* Initially set columnCount to 1, will be changed automatically later. */
        setColumnCount(1);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        super.onMeasure(widthSpec, heightSpec);

        int width = MeasureSpec.getSize(widthSpec);
        if (columnWidth > 0 && width > 0) {
            int totalSpace = width - getPaddingRight() - getPaddingLeft();
            int columnCount = Math.max(1, totalSpace / columnWidth);
            setColumnCount(columnCount);
        } else {
            setColumnCount(defaultColumnCount);
        }
    }
}

Just add to your XML layout file like this:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.km.myproject.customview.AutoGridLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnCount="5"
        app:columnWidth="50dp"/>

</FrameLayout>

Using columnWidth will try to calculate how many columns can fit and set the optimal span count automatically. If not used (or failed to measure for some reason), the columnCount attribute will be used.

Hope this helps!

like image 45
km. Avatar answered Sep 28 '22 05:09

km.