Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force GridView to generate square cells in Android

How can I force an android GridView to generate square cells (Cell's height equal to cell's width) GridView has 10*9 cells and the app must support multiple screens !

I used a Linear Layout:

row_grid.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="0dp" >

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:src="@drawable/ic_launcher" >
        </ImageView>

    </LinearLayout>

and GridView: activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/katy" >

    <GridView
        android:id="@+id/gridView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:horizontalSpacing="0dp"
        android:numColumns="4"
        android:stretchMode="columnWidth"
        android:verticalSpacing="0dp" >
    </GridView>
</RelativeLayout>

Each cell of GridView contains a image that has same width and height. images are larger than cells and must stretch to fit in cells. enter image description here

like image 541
Jessica Avatar asked Jun 25 '14 19:06

Jessica


4 Answers

First, you're going to want to create a custom View class that you can use instead of the default LinearLayout you're using. Then you want to override the View's onMeasure call, and force it to be square:

public class GridViewItem extends ImageView {      public GridViewItem(Context context) {         super(context);     }      public GridViewItem(Context context, AttributeSet attrs) {         super(context, attrs);     }      public GridViewItem(Context context, AttributeSet attrs, int defStyle) {         super(context, attrs, defStyle);     }      @Override     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width     } } 

Then you can change your row_grid.xml file to:

<path.to.item.GridViewItem xmlns:android="http://schemas.android.com/apk/res/android"     android:id="@+id/item_image"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:scaleType="centerCrop"     android:src="@drawable/ic_launcher" > </path.to.item.GridViewItem> 

Just be sure to change "path.to.item" to the package where your GridViewItem.java class resides.

I also removed your LinearLayout parent since it wasn't doing anything for you there.

Edit:

Also changed scaleType from fitXY to centerCrop so that your image doesn't stretch itself and maintains its aspect ratio. And, as long as it's a square image, nothing should be cropped, regardless.

like image 138
Cruceo Avatar answered Sep 19 '22 22:09

Cruceo


You can Override your linear layout

public class MyLinearLayout extends LinearLayout {     public MyLinearLayout(Context context) {         super(context);     }      public MyLinearLayout(Context context, AttributeSet attrs) {         super(context, attrs);     }      public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);     }     @Override     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width     } } 

then use it in the item_grid.xml

<?xml version="1.0" encoding="utf-8"?> <com.example.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="vertical"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="@drawable/item_grid"      android:layout_margin="2dp"     android:padding="3dp"     android:gravity="center">      <TextView         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="Category Name"         android:textStyle="bold"         android:textColor="@color/colorPrimary"         android:id="@+id/tvCategoryName" />   </com.example.MyLinearLayout> 
like image 38
Hossam Alaa Avatar answered Sep 18 '22 22:09

Hossam Alaa


How about using ConstraintLayout?

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:padding="3dp">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
like image 42
Yuki.M Avatar answered Sep 16 '22 22:09

Yuki.M


Works nicely, thank you! A small improvement I required would be always pick the smaller value, to prevent overshooting the screen:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if(heightMeasureSpec < widthMeasureSpec) {
        super.onMeasure(heightMeasureSpec, heightMeasureSpec);
    } else if(widthMeasureSpec < heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
    } else {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

}
like image 21
最白目 Avatar answered Sep 20 '22 22:09

最白目