Android GridVIew Изменение количества столбцов в зависимости от ориентации

Я хочу отобразить 6 изображений в виде сетки следующим образом.

в портретной ориентации, 2 coumns, 3 ряда и в ориентации на ландшафт 3 столбца, 2 строки

Используя Android GridView и определяя различные макеты сетки в каталогах макета-порта и макета-земли, я смог добиться этого эффекта.

Позже в соответствии с моим требованием к работе я добавил один параметр в manifest.xml, который

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

чтобы остановить мою активность, чтобы воссоздать после изменения ориентации экрана.

После добавления этого параметра мой вид сетки не ведет себя ожидаемым образом. Он иногда показывает 1 столбец, иногда 2 столбца, а иногда и 3 столбца.

Я размещаю методы gridView.setNumberOfColumns(2) или gridView.setNumberOfColumns(3) в методе получения моего адаптера сетки в зависимости от ориентации устройства.

Пожалуйста, помогите мне достичь этого эффекта, не удалив параметр android:configChanges в Manifest.xml

Ответ 1

Используйте мощную систему ресурсов.

В макете xml задайте количество столбцов для целочисленного ресурса, а затем в /values/integers.xml установите для него значение 2 для портрета и в /values-land/integers.xml установите для него значение 3 для пейзажа

//хорошо, если вы выполните configChanges в манифесте, вам придется изменить количество столбцов из java в onConfogurationChanged

Ответ 2

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

Ответ 3

вы можете установить число столбцов программно, используя

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

Ответ 4

Мое решение:

значения /dimens.xml:

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

макет /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"/>

в вашем фрагменте:

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();
}

Ответ 5

    @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);
        }

    };

Затем снова загрузите данные в gridview в соответствии с вашими потребностями.

Поместите андроид: configChanges = "ориентация" для этой активности node в манифесте.

Ответ 6

Пока вы используете android: configChanges = "ориентация" в манифесте, ваша активность не воссоздается при изменении ориентации ( "Пейзаж для портрета" или наоборот). Если вы не хотите удалять этот тег из манифеста, вам необходимо переопределить onConfigchanged и поместить туда некоторую логику кода.

Ответ 7

я сделал его на основе размера экрана, но не 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;
}