Gridview的高度被削减


124

我正在尝试在gridview中显示8个项目。可悲的是,gridview的高度总是太小,因此它仅显示第一行,而第二行的一小部分。

设置android:layout_height="300dp"使它起作用。wrap_ contentfill_parent显然不是。

我的网格视图:

<GridView
    android:id="@+id/myId"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:horizontalSpacing="2dp"
    android:isScrollContainer="false"
    android:numColumns="4"
    android:stretchMode="columnWidth"
    android:verticalSpacing="20dp" />

我的物品资源:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:minHeight="?android:attr/listPreferredItemHeight" >

    <ImageView
        android:id="@+id/appItemIcon"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_dialog_info"
        android:scaleType="center" />      

    <TextView
        android:id="@+id/appItemText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="My long application name"
        android:gravity="center_horizontal"
        android:textAppearance="?android:attr/textAppearanceSmall" />

</LinearLayout>

这个问题似乎与缺乏垂直空间无关。

我能做什么 ?


Answers:


351

经过(太多)研究,我偶然发现了尼尔·特拉夫特(Neil Traft)的出色回答

适应他的工作GridView已经很容易了。

ExpandableHeightGridView.java:

package com.example;
public class ExpandableHeightGridView extends GridView
{

    boolean expanded = false;

    public ExpandableHeightGridView(Context context)
    {
        super(context);
    }

    public ExpandableHeightGridView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public ExpandableHeightGridView(Context context, AttributeSet attrs,
            int defStyle)
    {
        super(context, attrs, defStyle);
    }

    public boolean isExpanded()
    {
        return expanded;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // HACK! TAKE THAT ANDROID!
        if (isExpanded())
        {
            // Calculate entire height by providing a very large height hint.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
                    MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);

            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
        }
        else
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    public void setExpanded(boolean expanded)
    {
        this.expanded = expanded;
    }
}

将其包含在您的布局中,如下所示:

<com.example.ExpandableHeightGridView
    android:id="@+id/myId"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:horizontalSpacing="2dp"
    android:isScrollContainer="false"
    android:numColumns="4"
    android:stretchMode="columnWidth"
    android:verticalSpacing="20dp" />

最后,您只需要让它扩展即可:

mAppsGrid = (ExpandableHeightGridView) findViewById(R.id.myId);
mAppsGrid.setExpanded(true);

20
此解决方案的内存使用效率不高,如果单元格是图像,则应用程序将崩溃。该解决方案告诉scrollview整个gridview的高度是多少,因此它可以下降,但是问题在于这样做可以渲染所有内容而无需使用回收。最多只能处理200个项目。
马里亚诺·拉托雷

7
@adamp我认为有一些有用的案例。如果要显示到2d数组中的项目数量有限,使用这种GridView似乎比尝试创建某种自定义/动态TableLayout容易,不是吗?
greg7gkb

5
对我不起作用,我将ExpandableHeightGridView放在了ScrollView下,它剪切了最后一个视图。
Chirag Nagariya

3
@tacone在网络上的框架,支持库和其他开放源代码中,可以找到许多更好的解决方案,其中最简单的方法是简单的for循环从适配器或其他地方获取视图。将它们添加到GridLayout(不是GridView; GridLayout也可在支持库中获得)TableLayout或类似的东西。
adamp

11
@adamp如果这不​​好,请添加您可以想到的最佳解决方案的答案
aleb 2014年

34

使用@tacone的答案并确保其有效后,我决定尝试缩短代码。这是我的结果。PS:这相当于将Tacones答案中的布尔值“ expanded”始终设置为true。

public class StaticGridView extends GridView {

    public StaticGridView(Context context) {
        super(context);
    }

    public StaticGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public StaticGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST));
        getLayoutParams().height = getMeasuredHeight();
    }
}

但是,等等-这仍然遭受内存使用的问题。你不再回收了吗?
Fattie

6

另一种对我有用的方法是计算一行的高度,然后使用静态数据(您可以对其进行分页)来计算您拥有的行数并轻松调整GridView的高度。

    private void resizeGridView(GridView gridView, int items, int columns) {
    ViewGroup.LayoutParams params = gridView.getLayoutParams();
    int oneRowHeight = gridView.getHeight();
    int rows = (int) (items / columns);
    params.height = oneRowHeight * rows;
    gridView.setLayoutParams(params);
}

设置适配器后以及绘制GridView时使用此代码,否则将得到height = 0。

gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (!gridViewResized) {
                    gridViewResized = true;
                    resizeGridView(gridView, numItems, numColumns);
                }
            }
        });

1
这对我来说效果很好-我在ListView中使用了一堆GridViews。不知道这是否是个坏主意-需要调查大型数据集的性能。但是无论如何,感谢您的代码。我认为虽然有一个错误的错误-我不得不使用int rows = items / columns + 1;
Andrew

对于低于android os 5.0的我收到此错误java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
silverFoxA 2015年

ViewGroup.LayoutParams参数= gridView.getLayoutParams(); 引发NullPointerException
Luke Allison

4

发现炸玉米饼回答有用...所以我将其移植到C#(Xamarin)

public class ExpandableHeightGridView: GridView
{
    bool _isExpanded = false;

    public ExpandableHeightGridView(Context context) : base(context)
    {            
    }

    public ExpandableHeightGridView(Context context, IAttributeSet attrs) : base(context, attrs)
    {            
    }

    public ExpandableHeightGridView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {            
    }

    public bool IsExpanded
    {
        get { return _isExpanded; }

        set { _isExpanded = value;  }
    }

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // HACK! TAKE THAT ANDROID!
        if (IsExpanded)
        {
            // Calculate entire height by providing a very large height hint.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.MakeMeasureSpec( View.MeasuredSizeMask, MeasureSpecMode.AtMost);
            base.OnMeasure(widthMeasureSpec,expandSpec);                

            var layoutParameters = this.LayoutParameters;
            layoutParameters.Height = this.MeasuredHeight;
        }
        else
        {
            base.OnMeasure(widthMeasureSpec,heightMeasureSpec);    
        }
    }
}

1
荣誉老兄。在xamarin.android中效果很好
Suchith 2016年

0

只需计算AT_MOST的高度并将其设置为测量即可。在这里GridView Scroll不能正常工作。需要明确使用垂直滚动视图。

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     int heightSpec;

     if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {

         heightSpec = MeasureSpec.makeMeasureSpec(
                        Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
     }
     else {
         // Any other height should be respected as is.
         heightSpec = heightMeasureSpec;
     }

     super.onMeasure(widthMeasureSpec, heightSpec);
 }

此方法是否可帮助您滚动GridView
Suchith,2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.