srikanth sanagapalli
srikanth sanagapalli

Reputation: 509

Android GridVIew Change number of columns depending on Orientation

I want to display 6 images in the form of grid as follows.

in portrait orientation,2 coumns, 3 rows and in landscare orientation 3 columns, 2 rows

By using Android GridView and by defining different grid layouts in layout-port and layout-land directories I was able to achieve this effect.

Later as per my activity requirement, I added one parameter in manifest.xml that is

android:configChanges = "mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale|screenSize"`

to stop my activity to recreate once screen orientation changes.

After adding this parameter, my grid view is not behaving in expected way. It sometimes shows 1 column, sometimes 2 columns, and sometimes 3 columns.

I am placing gridView.setNumberOfColumns(2) or gridView.setNumberOfColumns(3) methods in the get view method of my grid adapter depending on orientation of the device.

Please help me to achieve this effect without removing the android:configChanges parameter in Manifest.xml

Upvotes: 16

Views: 40294

Answers (9)

Baby Love
Baby Love

Reputation: 46

add this code to onCreate

 gridView_menu.setNumColumns(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? 3:4);

Upvotes: 0

Lou Morda
Lou Morda

Reputation: 5165

Here's the XML:

<GridLayout
    android:id="@+id/gridLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="@integer/num_columns"
    android:rowCount="@integer/num_rows"
    android:orientation="vertical">
    <!-- TextViews, ImageViews, etc -->
</GridLayout>

And then inside your fragment:

@BindView(R.id.gridLayout) GridLayout gridLayout;

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    final ArrayList<View> views = new ArrayList<>();
    for (int i = 0; i < gridLayout.getChildCount(); i++) {
        views.add(gridLayout.getChildAt(i));
    }
    gridLayout.removeAllViews();
    gridLayout.setColumnCount(getContext().getResources().getInteger(R.integer.num_columns));
    gridLayout.setRowCount(getContext().getResources().getInteger(R.integer.num_rows));
    for (int i = 0; i < views.size(); i++) {
        views.get(i).setLayoutParams(new GridLayout.LayoutParams());
        gridLayout.addView(views.get(i));
    }
}

Upvotes: 0

John
John

Reputation: 1543

i made it based by screen size, not dpi

public static int getGridColumnsCount(Context context){
    boolean landscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;

    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    float hi=displayMetrics.heightPixels/displayMetrics.xdpi;
    float wi=displayMetrics.widthPixels/displayMetrics.ydpi;
    float screenWidthInch  = landscape ? Math.max(wi, hi) : Math.min(wi, hi);
    float screenWidthCm = screenWidthInch * 2.54f;
    int columns = (int)(screenWidthCm/2);
    return columns < 3 ? 3 : columns;
}

Upvotes: 1

almisoft
almisoft

Reputation: 2183

My solution:

values/dimens.xml:

<resources>
    <dimen name="grip_view_entry_size">160dp</dimen>
    <dimen name="grip_view_spacing">10dp</dimen>
</resources>

layout/gridview.xml

<GridView android:id="@+id/android:list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="auto_fit"
    android:verticalSpacing="@dimen/grip_view_spacing"
    android:horizontalSpacing="@dimen/grip_view_spacing"
    android:stretchMode="columnWidth"
    android:gravity="center"
    android:scrollingCache="false"
    android:fastScrollEnabled="true"
    android:animationCache="false"/>

in your fragment:

private void refreshGridView() {

    int gridViewEntrySize = getResources().getDimensionPixelSize(R.dimen.grip_view_entry_size);
    int gridViewSpacing = getResources().getDimensionPixelSize(R.dimen.grip_view_spacing);

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();

    int numColumns = (display.getWidth() - gridViewSpacing) / (gridViewEntrySize + gridViewSpacing);

    gridView.setNumColumns(numColumns);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    refreshGridView();
}

@Override
public void onResume() {
    super.onResume();
    refreshGridView();
}

Upvotes: 4

urSus
urSus

Reputation: 12739

Use the powerful resource system.

In the xml layout, set the number of columns to a integer resource and then in /values/integers.xml set it to 2 for portrait and in /values-land/integers.xml set it to 3 for landscape

// well, if you do configChanges in manifest, you will have to change column count from java in onConfogurationChanged

Upvotes: 44

Pratik Butani
Pratik Butani

Reputation: 62421

you can set number of columns programatically using

float scalefactor = getResources().getDisplayMetrics().density * 100;
int number = getWindowManager().getDefaultDisplay().getWidth();
int columns = (int) ((float) number / (float) scalefactor);
gridView.setNumColumns(columns);

Upvotes: 6

Jin35
Jin35

Reputation: 8612

@Override
public void onConfigurationChanged(Configuration newConfig) {
    grid.setNumColumns(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ? 3 : 2);
    super.onConfigurationChanged(newConfig);
}

Upvotes: 12

Amit Hooda
Amit Hooda

Reputation: 2144

    @Override
    public void onConfigurationChanged(Configuration newConfig) {

        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.lay_vertical);
        } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            setContentView(R.layout.lay_horizontal);
        }

    };

Then load the data in gridview again according to your need.

Put android:configChanges="orientation" for that activity node in the manifest.

Upvotes: 2

Krishnakant Dalal
Krishnakant Dalal

Reputation: 3578

While you use android:configChanges = "orientation" in manifest your activity does not recreate on orientation changed (Landscape to Portrait or vice versa). If you don't want to remove this tag from manifest you must have to override onConfigchanged and put some code logic there.

Upvotes: 1

Related Questions