Создание элементов таблицы 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));