I would like the items of my GridView
to be square. There are 2 columns and the items width is fill_parent
(e.g. they take as much horizontal space as possible. The items are custom views.
How do I make the items height to be equal to their variable width?
There is a simpler solution when GridView columns are stretched. Just override the onMeasure of the GridView item layout with...
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
Or if you want to extend a View just do something really simple like:
public class SquareImageView extends ImageView
{
public SquareImageView(final Context context)
{
super(context);
}
public SquareImageView(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public SquareImageView(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
final int width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
setMeasuredDimension(width, width);
}
@Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh)
{
super.onSizeChanged(w, w, oldw, oldh);
}
}
It's worth noting that super.onMeasure()
is not needed. onMeasured
requirement is that you must call setMeasuredDimension
.
I'm not sure this is possible with the current widgets. Your best bet might be to put your custom view in a custom "SquareView". This view could just contain 1 child view, and force the height to equal the width when its onLayout method is called.
I never tried to do something like that, but I think it shouldn't be too difficult. An alternative (and maybe slightly easier) solution might be to subclass your custom view's root layout (like, if it's a LinearLayout, make a SquareLinearLayout), and use that as a container instead.
edit : Here's a basic implementation which seems to work for me :
package com.mantano.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class SquareView extends ViewGroup {
public SquareView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int l, int u, int r, int d) {
getChildAt(0).layout(0, 0, r-l, d-u); // Layout with max size
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View child = getChildAt(0);
child.measure(widthMeasureSpec, widthMeasureSpec);
int width = resolveSize(child.getMeasuredWidth(), widthMeasureSpec);
child.measure(width, width); // 2nd pass with the correct size
setMeasuredDimension(width, width);
}
}
It's designed to have a unique child, but I ignored all of the checks for the sake of simplicity. The basic idea is to measure the child with the width/height parameters set by the GridView (in my case, it uses numColumns=4 to calculate the width), and then do a second pass with the final dimensions, with height=width... The layout is just a plain layout, which layouts the unique child at (0, 0) with the desired dimensions (right-left, down-up).
And here's the XML used for the GridView items :
<?xml version="1.0" encoding="utf-8"?>
<com.mantano.widget.SquareView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<LinearLayout android:id="@+id/item" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="horizontal"
android:gravity="center">
<TextView android:id="@+id/text" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Hello world" />
</LinearLayout>
</com.mantano.widget.SquareView>
I used a LinearLayout inside the SquareView in order to have it manage all the gravity possibilities, margins, etc.
I'm not sure how well (or bad) this widget would react to orientation and dimension changes, but it seems to work correctly.
It ends up being fairly easy to get the grid item square.
In your "GetView" method of your grid adapter, just do:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
GridView grid = (GridView)parent;
int size = grid.getRequestedColumnWidth();
TextView text = new TextView(getContext());
text.setLayoutParams(new GridView.LayoutParams(size, size));
// Whatever else you need to set on your view
return text;
}
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