Создание элементов таблицы GridView

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

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

Ответ 1

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

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}

Ответ 2

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

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.

Ответ 3

Я не уверен, что это возможно с текущими виджетами. Лучше всего поставить свой пользовательский вид в пользовательский "SquareView". Этот вид может содержать только одно дочернее представление и заставлять высоту равняться ширине при вызове метода 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);
    }
}

Он предназначен для создания уникального ребенка, но я просто проигнорировал все проверки для простоты. Основная идея состоит в том, чтобы измерить дочерний элемент с параметрами width/height, заданными 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, чтобы он мог управлять всеми возможностями гравитации, полями и т.д.

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

Ответ 4

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

В вашем методе 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;
}

Ответ 5

Я не знаю, если это лучший способ, но я выполняю то, что делает мой пользовательский вид переопределять 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, и в обоих он показывает квадрат!

Ответ 6

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

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

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

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

  • в вашем адаптере (в getView (int position, View convertView, родитель ViewGroup))

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

  • 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" />

  • 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" />

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

Ответ 7

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

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

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

    item_side = mFragment.holder.grid.getWidth() / N_COL;
    v.getLayoutParams().height = item_side;
    v.getLayoutParams().width = item_side;

Ответ 8

Это то, что я делаю, чтобы показать квадратные ячейки в 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) );

Ответ 9

Попробуйте

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

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

Ответ 10

На основе ответа SteveBorkman, который является 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;
}

Ответ 11

По линии ответа @Gregory мне пришлось обернуть мое изображение в LinearLayout, чтобы GridView не манипулировал своими размерами из квадрата. Обратите внимание, что внешний LinearLayout должен быть установлен так, чтобы иметь размер изображения, а ширина столбца GridView должна быть шириной изображения PLUS любого поля. Например:

    <!-- LinearLayout wrapper necessary to wrap image button in order to keep square;
    otherwise, the grid view distorts it into rectangle.

    also, margin top and right allows the indicator overlay to extend top and right.

    NB: grid width is set in filter_icon_page.xml, and must correspond to size + margin
    -->
<LinearLayout
        android:id="@+id/sport_icon_lay"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:orientation="vertical"

        android:layout_marginRight="6dp"
        android:layout_marginTop="6dp"
        >

    <ImageButton
            android:id="@+id/sport_icon"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:maxHeight="60dp"
            android:maxWidth="60dp"
            android:scaleType="fitCenter"
            />
</LinearLayout>

и GridView:

   <GridView
        android:id="@+id/grid"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:fillViewport="true"

        android:columnWidth="66dp"

        android:numColumns="auto_fit"
        android:verticalSpacing="25dp"
        android:horizontalSpacing="24dp"
        android:stretchMode="spacingWidth"

        />

Ответ 12

В вашей деятельности

 DisplayMetrics displaymetrics = new DisplayMetrics();
 getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
 valX = displaymetrics.widthPixels/columns_number;

в CustomAdapter GridView

 v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, YourActivity.valX));