Android custom GridView scalable (auto adjusting col width)

Its all ways digusting me when using Android grid view because the cols are not free flowing even though we set the cols to expand and the solution is we need to set the col width dynamically by calculating with the screen width to the number of cols drawn.
This is what we are going to achieve:
Here is how it can be done:
Step 1: Create a new project and add GridView to main xml:
<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/albumGrid" style="@style/PhotoGrid" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/black" android:columnWidth="@dimen/photo_size" android:horizontalSpacing="@dimen/photo_spacing" android:numColumns="auto_fit" android:padding="4dp" android:scrollbars="none" android:stretchMode="columnWidth" android:verticalSpacing="@dimen/photo_spacing" />
Step 2: Make your main activity exactly as below.
[The code below is self explained where ever required through comments].
public class MainActivity extends Activity { private GridView photoGrid; private int mPhotoSize, mPhotoSpacing; private ImageAdapter imageAdapter; // Some items to add to the GRID private static final String[] CONTENT = new String[] { "Akon", "Justin Bieber", "AlRight", "Big Sean", "Britney Spears", "Hilary", "Micheal Buble", "Akon", "Justin Bieber", "AlRight", "Big Sean", "Britney Spears", "Hilary", "Micheal Buble", "Britney Spears", "Hilary", "Micheal Buble", "Akon", "Justin Bieber", "AlRight", "Big Sean", "Britney Spears", "Hilary", "Micheal Buble", "Akon", "Justin Bieber", "AlRight", "Big Sean", "Britney Spears", "Hilary", "Micheal Buble", "Akon", "Justin Bieber", "AlRight", "Big Sean", "Britney Spears", "Hilary", "Micheal Buble", "Britney Spears", "Hilary", "Micheal Buble", "Akon", "Justin Bieber", "AlRight", "Big Sean", "Britney Spears", "Hilary", "Micheal Buble" }; private static final int[] ICONS = new int[] { R.drawable.cover_akon, R.drawable.cover_justin, R.drawable.cover_alright, R.drawable.cover_big_sean, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb, R.drawable.cover_akon, R.drawable.cover_justin, R.drawable.cover_alright, R.drawable.cover_big_sean, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb, R.drawable.cover_akon, R.drawable.cover_justin, R.drawable.cover_alright, R.drawable.cover_big_sean, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb, R.drawable.cover_akon, R.drawable.cover_justin, R.drawable.cover_alright, R.drawable.cover_big_sean, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb, R.drawable.cover_akon, R.drawable.cover_justin, R.drawable.cover_alright, R.drawable.cover_big_sean, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb, R.drawable.cover_akon, R.drawable.cover_justin, R.drawable.cover_alright, R.drawable.cover_big_sean, R.drawable.cover_britney, R.drawable.cover_hilary, R.drawable.cover_mb }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // get the photo size and spacing mPhotoSize = getResources().getDimensionPixelSize(R.dimen.photo_size); mPhotoSpacing = getResources().getDimensionPixelSize(R.dimen.photo_spacing); // initialize image adapter imageAdapter = new ImageAdapter(); photoGrid = (GridView) findViewById(R.id.albumGrid); // set image adapter to the GridView photoGrid.setAdapter(imageAdapter); // get the view tree observer of the grid and set the height and numcols dynamically photoGrid.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (imageAdapter.getNumColumns() == 0) { final int numColumns = (int) Math.floor(photoGrid.getWidth() / (mPhotoSize + mPhotoSpacing)); if (numColumns > 0) { final int columnWidth = (photoGrid.getWidth() / numColumns) - mPhotoSpacing; imageAdapter.setNumColumns(numColumns); imageAdapter.setItemHeight(columnWidth); } } } }); } // ///////// ImageAdapter class ///////////////// public class ImageAdapter extends BaseAdapter { private LayoutInflater mInflater; private int mItemHeight = 0; private int mNumColumns = 0; private RelativeLayout.LayoutParams mImageViewLayoutParams; public ImageAdapter() { mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); mImageViewLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } public int getCount() { return CONTENT.length; } // set numcols public void setNumColumns(int numColumns) { mNumColumns = numColumns; } public int getNumColumns() { return mNumColumns; } // set photo item height public void setItemHeight(int height) { if (height == mItemHeight) { return; } mItemHeight = height; mImageViewLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, mItemHeight); notifyDataSetChanged(); } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(final int position, View view, ViewGroup parent) { if (view == null) view = mInflater.inflate(R.layout.photo_item, null); ImageView cover = (ImageView) view.findViewById(R.id.cover); TextView title = (TextView) view.findViewById(R.id.title); cover.setLayoutParams(mImageViewLayoutParams); // Check the height matches our calculated column width if (cover.getLayoutParams().height != mItemHeight) { cover.setLayoutParams(mImageViewLayoutParams); } cover.setImageResource(ICONS[position % ICONS.length]); title.setText(CONTENT[position % CONTENT.length]); return view; } } }
Step 3: Add these files to the values folder:
colors.xml :
<resources> <color name="grid_state_pressed">#BB561e14</color> <color name="grid_state_focused">#77561e14</color> <color name="transparent">#00000000</color> <color name="white">#fff</color> <color name="black">#000</color> </resources>
dimens.xml :
<resources> <dimen name="photo_size">120dp</dimen> <dimen name="photo_spacing">4dp</dimen> </resources>
styles.xml :
<resources> <!-- Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vXX/styles.xml on newer devices. --> <style name="AppBaseTheme" parent="android:Theme.Light"> <!-- Theme customizations available in newer API levels can go in res/values-vXX/styles.xml, while customizations related to backward-compatibility can go here. --> </style> <!-- Application theme. --> <style name="AppTheme" parent="AppBaseTheme"> <!-- All customizations that are NOT specific to a particular API-level can go here. --> </style> <style name="PhotoGrid"> <item name="android:drawSelectorOnTop">true</item> <item name="android:listSelector">@drawable/photogrid_selector</item> </style> </resources>