Создание элементов GridView квадратными - PullRequest
77 голосов
/ 02 июля 2011

Я бы хотел, чтобы элементы моего GridView были квадратными.Имеется 2 столбца, а ширина элементов равна fill_parent (например, они занимают как можно больше горизонтального пространства. Элементы представляют собой пользовательские виды.

Как сделать высоту элементов равной их переменной ширине?

Ответы [ 12 ]

107 голосов
/ 15 апреля 2012

Существует более простое решение, когда столбцы GridView растянуты. Просто переопределите onMeasure макета элемента GridView с помощью ...

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
53 голосов
/ 14 февраля 2013

Или, если вы хотите расширить View, просто сделайте что-нибудь действительно простое, например:

public class SquareImageView extends ImageView
{

    public SquareImageView(final Context context)
    {
        super(context);
    }

    public SquareImageView(final Context context, final AttributeSet attrs)
    {
        super(context, attrs);
    }

    public SquareImageView(final Context context, final AttributeSet attrs, final int defStyle)
    {
        super(context, attrs, defStyle);
    }


    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
    {
        final int width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
        setMeasuredDimension(width, width);
    }

    @Override
    protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh)
    {
        super.onSizeChanged(w, w, oldw, oldh);
    }
}

Стоит отметить, что super.onMeasure() не нужен. onMeasured Требуется, чтобы вы позвонили setMeasuredDimension.

15 голосов
/ 02 июля 2011

Я не уверен, что это возможно с текущими виджетами.Лучше всего было бы поместить свой пользовательский вид в пользовательский "SquareView".Это представление может содержать только 1 дочернее представление и принудительно устанавливать высоту равной ширине при вызове его метода onLayout.

Я никогда не пытался сделать что-то подобное, но я думаю, что это не должно быть слишком сложно.Альтернативное (и, возможно, немного более простое) решение может заключаться в создании подкласса корневого макета вашего пользовательского представления (например, если это LinearLayout, создание SquareLinearLayout) и использовании его вместо контейнера.

edit: вот базовыйреализация, которая, кажется, работает для меня:

package com.mantano.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class SquareView extends ViewGroup {

    public SquareView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int u, int r, int d) {
        getChildAt(0).layout(0, 0, r-l, d-u); // Layout with max size
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        View child = getChildAt(0);
        child.measure(widthMeasureSpec, widthMeasureSpec);
        int width = resolveSize(child.getMeasuredWidth(), widthMeasureSpec);
        child.measure(width, width); // 2nd pass with the correct size
        setMeasuredDimension(width, width);
    }
}

Она предназначена для того, чтобы иметь уникального потомка, но я упустил все проверки ради простоты.Основная идея состоит в том, чтобы измерить дочерний элемент с параметрами ширины / высоты, установленными GridView (в моем случае он использует numColumns = 4 для вычисления ширины), а затем выполнить второй проход с окончательными размерами, при этом высота = ширина... Макет представляет собой просто простой макет, который размещает уникальный дочерний элемент в (0, 0) с желаемыми размерами (справа налево, вниз).

А вот XML, используемый для элементов GridView:

<?xml version="1.0" encoding="utf-8"?>
<com.mantano.widget.SquareView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="wrap_content">

    <LinearLayout android:id="@+id/item" android:layout_width="fill_parent"
        android:layout_height="fill_parent" android:orientation="horizontal"
        android:gravity="center">

        <TextView android:id="@+id/text" android:layout_width="fill_parent"
            android:layout_height="wrap_content" android:text="Hello world" />
    </LinearLayout>
</com.mantano.widget.SquareView>

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

Я не уверен, насколько хорошо (или плохо) этоВиджет будет реагировать на изменения ориентации и размеров, но, похоже, он работает правильно.

12 голосов
/ 16 сентября 2014

Получается достаточно просто получить квадрат элемента сетки.

В вашем методе "GetView" вашего адаптера сетки просто выполните:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    GridView grid = (GridView)parent;
    int size = grid.getRequestedColumnWidth();

    TextView text = new TextView(getContext());
    text.setLayoutParams(new GridView.LayoutParams(size, size));

    // Whatever else you need to set on your view

    return text;
}
6 голосов
/ 07 января 2015

Это сработало для меня!

Если вы похожи на меня и не можете использовать getRequestedColumnWidth (), поскольку ваш minSdk меньше 16, я предлагаю эту опцию.

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

    DisplayMetrics dm = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); int size = dm.widthPixels / nbColumns; CustomAdapter adapter = new CustomAdapter(list, size, getActivity());

  2. в вашем адаптере (в getView (позиция int, View convertView, родительский элемент ViewGroup))

    v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));

  3. fragment.xml:

    <GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="match_parent" android:horizontalSpacing="3dp" android:verticalSpacing="3dp" android:numColumns="4" android:stretchMode="columnWidth" />

  4. custom_item.xml: (например)

    <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/picture" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" />

Надеюсь, это кому-нибудь поможет!

6 голосов
/ 28 апреля 2012

Я не знаю, является ли это лучшим способом, но я добиваюсь того, чтобы создание моего пользовательского представления переопределяло onSizeChanged таким образом:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    if (getLayoutParams() != null && w != h) {
        getLayoutParams().height = w;
        setLayoutParams(getLayoutParams());
    }
}

Я использую это пользовательское представление внутри LinearLayout и GridView ив обоих он показывает квадрат!

5 голосов
/ 19 декабря 2011

если вы установите статическое число столбцов в xml, то вы можете взять ширину представления и разделить ее на количество столбцов.

, если вы используете auto_fit, тогда это будетнемного сложно получить количество столбцов (нет метода getColumnCount ()), кстати этот вопрос должен вам как-то помочь.

это код, который я использую в getView(...) метод адаптера с фиксированным количеством столбцов:

    item_side = mFragment.holder.grid.getWidth() / N_COL;
    v.getLayoutParams().height = item_side;
    v.getLayoutParams().width = item_side;
4 голосов
/ 30 июля 2013

Попробуйте

<GridView
...
android:stretchMode="columnWidth" />

Вы также можете играть с другими режимами

4 голосов
/ 16 декабря 2011

Это то, что я делаю, чтобы показать квадратные ячейки в GridView. Я не уверен, хотите ли вы квадратные ячейки или что-то еще.

GridView grid = new GridView( this );
grid.setColumnWidth( UIScheme.cellSize );
grid.setVerticalSpacing( UIScheme.gap );
grid.setStretchMode( GridView.STRETCH_COLUMN_WIDTH );
grid.setNumColumns( GridView.AUTO_FIT );

И затем представление, которое я создаю для каждой ячейки, я должен сделать с ней следующее:

cell.setLayoutParams( new GridView.LayoutParams(iconSize, iconSize) );
3 голосов
/ 30 июня 2015

На основании ответа СтиваБоркмана , который является API 16 +:

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

    GridView grid = (GridView)parent;
    int size = grid.getColumnWidth();

    if (convertView == null){
        convertView = LayoutInflater.from(context).inflate(R.layout.your_item, null);
        convertView.setLayoutParams(new GridView.LayoutParams(size, size));
    }

     //Modify your convertView here

     return convertView;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...