使 GridView 项目正方形

我希望我的 GridView项目是正方形的。有2列,项目宽度是 fill_parent(例如,他们需要尽可能多的水平空间。这些项是自定义视图。

如何使项目的高度等于它们的可变宽度?

64155 次浏览

I'm not sure this is possible with the current widgets. Your best bet might be to put your custom view in a custom "SquareView". This view could just contain 1 child view, and force the height to equal the width when its onLayout method is called.

我从来没有尝试过做这样的事情,但我认为这应该不会太困难。一个替代的(也许稍微简单一些)解决方案可能是子类化自定义视图的根布局(比如,如果它是一个 LinearLayout,创建一个 SquareLinearLayout) ,并将其用作容器。

编辑: 这里有一个基本的实现,似乎对我有用:

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

It's designed to have a unique child, but I ignored all of the checks for the sake of simplicity. The basic idea is to measure the child with the width/height parameters set by the GridView (in my case, it uses numColumns=4 to calculate the width), and then do a second pass with the final dimensions, with height=width... 这个布局只是一个普通的布局,它使用所需的尺寸(从右到左,从下到上)在(0,0)处布局唯一的子元素。

And here's the XML used for the GridView items :

<?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>

我在 SquareView 内部使用了一个 linearLayout 来管理所有的重力可能性、利润率等等。

我不确定这个小部件对方向和维度变化的反应如何,但它似乎工作正常。

按照@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>

and the GridView like:

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


/>

这就是我在 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) );

if you set a static number of columns in the xml then you can take the width of the view and divide it by the number of columns.

如果您使用的是 auto_fit,那么获取列计数(没有 getColumnCount ()方法)就有点麻烦了,顺便说一句,this问题应该会对您有所帮助。

这是我在适配器的 getView(...)方法中使用的具有固定列数的代码:

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

有一个更简单的解决方案,当 GridView 列被拉伸时。

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

我不知道这是否是最好的方法,但我通过自定义视图覆盖 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 中使用这个自定义视图,它们都显示正方形!

Or if you want to extend a View just do something really simple like:

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

试试看

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

你也可以玩其他模式

在你的活动中

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

在 GridView 的 CustomAdapter 中

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

It ends up being fairly easy to get the grid item square.

在网格适配器的“ 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;
}

这招对我管用!

如果您和我一样,不能使用 getRequestedColumnWidth () ,因为 minSdk 小于16,我建议使用这个选项。

  1. 在你的碎片里:

    DisplayMetrics dm = 新的 DisplayMetrics () ; GetActivity () . getWindowManager () . getDefaultDisplay () . getMetrics (dm) ; Int size = dm.widthPixels/nbColumns; CustomAdapter Adapter = 新的 CustomAdapter (列表、大小、 getActivity ()) ;

  2. 在您的适配器中(在 getView 中(int 位置,View ConvertView,ViewGroup 父级))

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

  3. Xml:

    < GridView Android: id = “@+ id/gridView” Android: layout _ width = “ match _ parent” Android: layout _ height = “ match _ parent” 水平间距 = “3dp” android:verticalSpacing="3dp" NumColumns = “4” Android: retchMode = “ columnWidth”/>

  4. Custom_ item. xml: (例如)

    < ImageView 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”/>

Hope it will help someone!

基于 史蒂夫 · 博克曼的回答,即 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;
}