【发布时间】:2011-09-27 07:15:39
【问题描述】:
我希望我的GridView 的项目是方形的。有 2 列,项目宽度为 fill_parent(例如,它们占用尽可能多的水平空间。项目是自定义视图。
如何使项目的高度等于它们的可变宽度?
【问题讨论】:
我希望我的GridView 的项目是方形的。有 2 列,项目宽度为 fill_parent(例如,它们占用尽可能多的水平空间。项目是自定义视图。
如何使项目的高度等于它们的可变宽度?
【问题讨论】:
当 GridView 列被拉伸时,有一个更简单的解决方案。只需使用...覆盖 GridView 项目布局的 onMeasure...
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
【讨论】:
或者,如果您想扩展视图,只需执行一些非常简单的操作,例如:
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。
【讨论】:
super.onMeasure() ,则不会绘制放置在其中的 ImageView。所以它似乎是onMeasure 方法的第一行所必需的。
我不确定当前的小部件是否可行。您最好的选择可能是将您的自定义视图放在自定义的“SquareView”中。此视图可能只包含 1 个子视图,并在调用其 onLayout 方法时强制高度等于宽度。
我从未尝试过这样做,但我认为这应该不会太难。另一种(可能更简单)的解决方案可能是将自定义视图的根布局子类化(例如,如果它是 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);
}
}
它的设计目的是拥有一个独特的孩子,但为了简单起见,我忽略了所有检查。基本思想是用 GridView 设置的宽度/高度参数来测量孩子(在我的例子中,它使用 numColumns=4 来计算宽度),然后使用最终尺寸进行第二次传递,高度 = 宽度。 .. 布局只是一个简单的布局,它在 (0, 0) 处以所需的尺寸(从右到左,从下到上)布局唯一的孩子。
这里是用于 GridView 项目的 XML:
<?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,以便让它管理所有的重力可能性、边距等。
我不确定这个小部件对方向和尺寸变化的反应有多好(或差),但它似乎可以正常工作。
【讨论】:
最终获得网格项目正方形相当容易。
在您的网格适配器的“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;
}
【讨论】:
getColumnWidth 替换 getRequestedColumnWidth 并为我工作......谢谢!
我不知道这是否是最好的方法,但我做到了,让我的自定义视图以这种方式覆盖 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 中使用此自定义视图,并且在两者中都显示为正方形!
【讨论】:
这对我有用!
如果你和我一样不能使用 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 parent))
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));
片段.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" />
希望对某人有所帮助!
【讨论】:
如果您在 xml 中设置静态列数,那么您可以获取视图的宽度并将其除以列数。
如果您使用的是auto_fit,那么获取列数会有点棘手(没有 getColumnCount() 方法),顺便说一句,this 问题应该对您有所帮助。
这是我在具有固定列数的适配器的getView(...) 方法中使用的代码:
item_side = mFragment.holder.grid.getWidth() / N_COL;
v.getLayoutParams().height = item_side;
v.getLayoutParams().width = item_side;
【讨论】:
试试
<GridView
...
android:stretchMode="columnWidth" />
你也可以玩其他模式
【讨论】:
这就是我在 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) );
【讨论】:
基于SteveBorkman's answer,即 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;
}
【讨论】:
按照@Gregory 的回答,我不得不将我的图像包装在一个LinearLayout 中,以防止GridView 从正方形操纵它的尺寸。注意外部的LinearLayout应该设置成图片的尺寸,GridView列的宽度应该是图片的宽度加上任何边距。例如:
<!-- 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"
/>
【讨论】:
在你的活动中
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));
【讨论】: