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.
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.
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>
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>
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With