Android: How does GridView auto_fit find the number of columns?
Looking at the GridView source, it is clear that setting the padding and the height on your ImageView will not help you at all. When a column width is not specified, it just chooses a preset number of columns (2):
private void determineColumns(int availableSpace) {
...
if (mRequestedNumColumns == AUTO_FIT) {
if (requestedColumnWidth > 0) {
// Client told us to pick the number of columns
mNumColumns = (availableSpace + requestedHorizontalSpacing) /
(requestedColumnWidth + requestedHorizontalSpacing);
} else {
// Just make up a number if we don't have enough info
mNumColumns = 2;
}
} else {
// We picked the columns
mNumColumns = mRequestedNumColumns;
}
if (mNumColumns <= 0) {
mNumColumns = 1;
}
...
The solution is to measure your column size before setting the GridView's column width. Here is a quick way to measure Views offscreen:
public int measureCellWidth( Context context, View cell )
{
// We need a fake parent
FrameLayout buffer = new FrameLayout( context );
android.widget.AbsListView.LayoutParams layoutParams = new android.widget.AbsListView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
buffer.addView( cell, layoutParams);
cell.forceLayout();
cell.measure(1000, 1000);
int width = cell.getMeasuredWidth();
buffer.removeAllViews();
return width;
}
And then you just set the GridView's column width:
gridView.setColumnWidth( width );
Grid View auto number of columns depending on screen size
Just use different number of columns for different screen sizes - override value in different values
folder (small, normal, large, xlarge), see documentation.
Example:
Activity or fragment:
<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:horizontalSpacing="10dp"
android:numColumns="@integer/column_count"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:verticalSpacing="50dp"
/>
Item:
<ImageView
android:id="@+id/image"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
values/integers.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="column_count">2</integer>
</resources>
values-large/integers.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="column_count">3</integer>
</resources>
values-xlarge/integers.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="column_count">4</integer>
</resources>
Android gridview android:numColumns=auto_fit always create only two columns
It looks like the auto-fit setting only applies if you have fixed column widths. Here is the only place in GridView source code that uses the auto-fit setting:
private boolean determineColumns(int availableSpace) {
final int requestedHorizontalSpacing = mRequestedHorizontalSpacing;
final int stretchMode = mStretchMode;
final int requestedColumnWidth = mRequestedColumnWidth;
boolean didNotInitiallyFit = false;
if (mRequestedNumColumns == AUTO_FIT) {
if (requestedColumnWidth > 0) {
// Client told us to pick the number of columns
mNumColumns = (availableSpace + requestedHorizontalSpacing) /
(requestedColumnWidth + requestedHorizontalSpacing);
} else {
// Just make up a number if we don't have enough info
mNumColumns = 2;
}
}
This private function is called during the measure / layout process. Notice that within the auto-fit if statement, unless requestedColumnWidth > 0
, then you just get 2 columns, which is what you are seeing.
If a fixed width works for your app, then you need to put it in your XML like this:
<FrameLayout 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"
>
<GridView
android:id="@+id/gridView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="5dp"
android:numColumns="auto_fit"
android:columnWidth="30dp"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp">
</GridView>
</FrameLayout>
How to set number of columns in GridView according to minimal and maximal column width?
In the end it was much easier than I had thought in the beginning.
Android does it more or less automatically for you, if you:
- set
android:numColumns="auto_fit" android:stretchMode="columnWidth"
in the layout of the grid view and - set
android:minWidth="200dp"
in the layout of the views used for the grid view cells and - set
android:layout_width="match_parent" android:layout_height="match_parent"
in both
This means that each column must be at least 200 dp and android will determine the number of columns so that the maximal number of columns with a column width of at least 200 dp is set and if the column are wider it will stretch the cells (evenly).
I had more complicated solutions involving getViewTreeObserver().addOnGlobalLayoutListener()
to wait until the grid view had determined it's size than calculating the number of columns by myself and then setting an Adapter
but the solution above was identical in result and much less effort.
Related Topics
Fcm (Firebase Cloud Messaging) Push Notification with ASP.NET
App Not Setup: This App Is Still in Development Mode
Android Logcat Logs Chatty Module Line Expire Message
How to Implement Uncaughtexception Android
How to Populate Android Room Database Table on First Run
Play Rtsp Streaming in an Android Application
Materialcomponents Theme Alert Dialog Buttons
Cannot Resolve Method 'Getsupportfragmentmanager ( )' Inside Fragment
Android Retrofit - Onprogressupdate for Showing Progress Notification
Error: Execution Failed for Task ':App:Clean'. Unable to Delete File
Difference Between Build.Gradle (Project) and Build.Gradle (Module)
How to Dynamically Set Headers in Retrofit (Android)
Getting Certificate Details from an APK
Displaying Yuv Image in Android
Android How to Create Triangle and Rectangle Shape Programmatically