2011-07-02 51 views
76

我希望我的GridView的物品为正方形。有2列和物品宽度为fill_parent(例如,它们采取尽可能多的水平空间成为可能。该项目是自定义视图。制作GridView物品广场

如何让我的项目高度等于其可变宽度?

回答

15

我不确定这是否可以使用当前的小部件,最好的办法可能是将自定义视图放在一个自定义的“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来计算宽度),然后用height = width做最后一个尺寸的第二遍。 .. 布局只是一个普通的布局,它以(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以拥有它管理所有的重力可能性,利润率等

我不知道这个小部件对方向和尺寸变化的反应如何(或不好),但它似乎正常工作。

+0

这听起来都不错,唯一的问题是写正确onLayout(或onMeasure)。 Currenlty我在ItemAdapter.getView()中设置了高度/宽度,但我不喜欢这个解决方案。 – anagaf

+0

@anagaf我用我刚刚测试过的代码编辑了我的答案,这似乎有效。这很容易理解,所以它应该很容易修复,以防万一你发现一些故障^^(不知道我是否应该编辑或发布第二个答案,对不起,如果我做错了!) – Gregory

+1

上述布局doesn不工作---我不知道为什么,但是对于孩子来说有一些细微的布局问题,例如TextViews不会包装,RelativeLayouts会变得非常混乱。不过,我确实在这里找到了一个等价物:http://stackoverflow.com/questions/2948212/android-layout-with-sqare-buttons ...虽然我仍然需要调整它(它的尺寸基于最大尺寸而不仅仅是宽度)。 –

1

沿着@格雷戈里的答案,我不得不将我的图像包裹在一个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" 

     /> 
4

这是我在做什么,显示方形单元在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); 

然后我正在创建针对每个小区我认为做到以下几点吧:如果你设置的XML列的静态数量,那么你可以采取

cell.setLayoutParams(new GridView.LayoutParams(iconSize, iconSize)); 
+0

工作很棒!谢谢! – mDroidd

5

视图的宽度并将其除以列数。

如果您使用的是auto_fit那么获取列数会有点棘手(没有getColumnCount()方法),btw this问题应该可以帮助您。

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

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

这对我来说非常合适。很简单。 –

106

有一个简单的解决方案时的GridView列拉伸。只是覆盖在GridView项目布局的onMeasure与...

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

工程很棒。我在答案中错过了几件事:1.高度被忽略,宽度作为高度传递。 2.该方法应该在项目和网格本身中被覆盖。 –

+11

约1:??这是什么使得它方 - ” – mDroidd

+0

我们应该扩展的GridView类来实现这一点,如果是这样,我得到InflateException可否请您让我知道如何实现这一目标 –

6

我不`吨知道这是否是最好的方式,但我实现这个目标让我的自定义视图来覆盖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中使用这个自定义视图,并且它都显示正方形!

+0

哦,男人,你是一个拯救生命的人,我已经为此奋战了好几天。除非你有很多孩子,否则格雷戈里的答案可以正常工作;然后,正如注释所指出的那样,TextViews不会换行,大多数视图不会重新调整它们的边界。 但是这个修复了它! – Makario

52

或者,如果你想扩展视图只是做非常简单的事情,如:

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

+2

工程像魅力..谢谢克里斯:) –

+1

这个答案很简单,很好。 –

+0

@anagaf你能把它标记为答案吗? – cyrilchampier

3

尝试

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

您还可以与其他模式

+0

这对我而言是一个干净的解决方案。 – Laranjeiro

-1

在你的活动

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

它最终被相当容易y来获得网格项目的平方。

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

这是为我工作的唯一解决方案...非常感谢! – Zeba

+0

必须用“getColumnWidth”替换“getRequestedColumnWidth”,它对我来说很有用。谢谢! –

6

这为我工作!

如果你像我一样,你不能使用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位置,查看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" 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" />

希望这将帮助别人!

3

基于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; 
}