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>

이 문제는 수직 공간 부족과 관련이없는 것 같습니다.

어떡해 ?


답변:


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
이 솔루션은 메모리 효율적이지 않으며 셀이 이미지 인 경우 앱이 충돌합니다. 이 솔루션은 스크롤 뷰에 전체 그리드 뷰의 높이를 알려주므로 내려갈 수 있지만 문제는 재활용을 사용하지 않고 모든 것을 렌더링한다는 것입니다. 200 개 이상의 항목이 작동 할 수 없습니다.
Mariano Latorre 2013 년

7
@adamp 나는 이것에 대한 유용한 경우가 있다고 생각합니다. 2D 배열에 표시 할 항목 수가 제한되어있는 경우 이러한 종류의 GridView를 사용하면 일종의 사용자 지정 / 동적 TableLayout을 만드는 것보다 더 쉬워 보입니다.
greg7gkb

5
나를 위해 작동하지 않으며, ScrollView 아래에 ExpandableHeightGridView를두면 마지막 뷰가 잘립니다.
살짝 Nagariya

3
@tacone 프레임 워크, 지원 라이브러리 및 웹 전반의 기타 오픈 소스 코드에서 쉽게 사용할 수있는 이러한 종류의 문제에 대한 더 나은 솔루션이 많이 있습니다. 가장 쉬운 방법은 어댑터 또는 다른 곳에서 뷰를 가져 오는 간단한 for 루프 일 수 있습니다. GridLayout에 추가 (GridView가 아님; GridLayout는 지원 라이브러리에서도 사용 가능) TableLayout 또는 유사합니다.
adamp 2014 년

11
@adamp 이것이 좋지 않다면 생각할 수있는 최상의 솔루션으로 답변을 추가하십시오
aleb

34

@tacone의 답변을 사용하고 작동하는지 확인한 후 코드를 줄이기로 결정했습니다. 이것이 제 결과입니다. 추신 : 타콘 응답에서 부울 "확장"을 항상 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를 그릴 때이 코드를 사용하면 높이 = 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

안드로이드 OS 5.0 이하의 경우이 오류가 발생합니다java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
silverFoxA 2015

ViewGroup.LayoutParams params = gridView.getLayoutParams (); NullPointerException이 발생합니다
누가 복음 앨리슨

4

tacones 답변이 도움이되었으므로 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

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를 스크롤하는 데 도움이
됩니까
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.