8

I have a custom gridview with items like that

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center"
android:longClickable="false"
android:orientation="vertical" >

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="false"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:longClickable="false"
    android:text="0"
    android:textSize="60sp" />

 </LinearLayout>

I want my items to be squares and I want gridview to stretch width to fill all all width of screen in portrait orientation and all height in landscape orientation. It should look like this layout

Where A - is the side of a square and B is the margin width (it could be zero). I think that I should probably override onMeasure method, but what exactly should I do? Maybe anyone can help?

EDIT OK, I tried to set width and height of items manually in getView method of adapter, it's better, but still it's not what I wanted. How can I get rid of that spacing between columns?

enter image description here

user1685095
  • 5,787
  • 9
  • 51
  • 100
  • 1
    Check my answer on How to manage GridView http://stackoverflow.com/a/13835812/833622 – Sherif elKhatib Oct 31 '13 at 16:49
  • Basically what you suggesting is to manually calculate height and width of an item and then to pass this values to the adapter, right? While this would probably work, that is awkward solution imho. – user1685095 Oct 31 '13 at 17:10
  • Actually you will only set the adapter after the gridview has been measured. It is the same as using a GlobalLayoutListener. Once the gridview is measured you could calculate everything exactly. – Sherif elKhatib Oct 31 '13 at 19:58
  • I probably should implement my own custom adapter view, that would have properties that I want. Unfortunately, this would take relatively long time, as I haven't done that before. – user1685095 Nov 01 '13 at 03:27
  • try http://stackoverflow.com/questions/6557516/making-grid-view-items-square – Deni Erdyneev Mar 10 '16 at 17:27

2 Answers2

3

First, you're 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.

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.

Shirish Herwade
  • 11,461
  • 20
  • 72
  • 111
-1

So you need GridView that fits screen with both stretchMode="columnWidth" and stretchMode="rowWidth". Unfortunately, last one is not real attribute and you actually need to do this calculations at runtime, as Sherif elKhatib suggested.

GridView fits screen and stretches columns automatically for you.

<GridView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:stretchMode="columnWidth" />

So we just need to stretch row. Which we can do, by calculating how much rowHeight should be if we know height of GridView and rowsCount.

public class YourAdapter extends BaseAdapter {

   int rowsCount;

   @Override
   public View getView(int position, View convertView, ViewGroup parent) {

       View itemView = convertView;
       if (itemView == null) {
           itemView = layoutInflater.inflate(R.layout.item_view, parent, false);            
           int height = parent.getHeight();
           if (height > 0) {
               LayoutParams layoutParams = itemView.getLayoutParams();
               layoutParams.height = (int) (height / rowsCount);
           } // for the 1st item parent.getHeight() is not calculated yet       
       }
   }
}
Sergii Pechenizkyi
  • 22,227
  • 7
  • 60
  • 71
  • Not working. In landscape orientation it takes all screen width and just 3 rows can be seen. – user1685095 Nov 01 '13 at 18:46
  • Looks like this. https://dl.dropboxusercontent.com/u/28070056/Screenshot_2013-11-01-22-52-34.png And implemented as you suggested it throws null pointer exception on layoutParams. – user1685095 Nov 01 '13 at 18:54