ความสูงของ Gridview ถูกตัดออก


125

ฉันกำลังพยายามแสดง 8 รายการในมุมมองตาราง น่าเสียดายที่ความสูงของเส้นตารางมักจะน้อยเกินไปดังนั้นจึงแสดงเฉพาะแถวแรกและส่วนที่สองเล็กน้อย

การตั้งค่าandroid:layout_height="300dp"ทำให้ใช้งานได้ wrap_ contentและfill_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

หลังจาก (มากเกินไป) วิจัยผมสะดุดในคำตอบที่ดีของนีล 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 มีความสูงเท่าใดจึงจะสามารถลงไปได้ แต่ปัญหาคือการทำเช่นนั้นจะแสดงผลทุกอย่างโดยไม่ต้องใช้การรีไซเคิล ไม่มีแร่เกิน 200 รายการที่สามารถทำงานได้
Mariano Latorre

7
@adamp ฉันคิดว่ามีกรณีที่เป็นประโยชน์สำหรับเรื่องนี้ หากคุณมีรายการจำนวน จำกัด ที่จะแสดงในอาร์เรย์ 2d การใช้ GridView ประเภทนี้ดูเหมือนจะง่ายกว่าการพยายามสร้าง TableLayout ที่กำหนดเอง / ไดนามิกบางประเภทใช่ไหม
greg7gkb

5
ไม่ได้ผลสำหรับฉันฉันได้ใส่ ExpandableHeightGridView ภายใต้ ScrollView มันจะตัดมุมมองสุดท้าย
Chirag Nagariya

3
@tacone มีวิธีแก้ปัญหาที่ดีกว่าหลายวิธีสำหรับปัญหาประเภทนี้พร้อมใช้งานในเฟรมเวิร์กไลบรารีการสนับสนุนและรหัสโอเพนซอร์สอื่น ๆ บนเว็บซึ่งวิธีที่ง่ายที่สุดอาจเป็นการดึง Views จากอะแดปเตอร์หรือที่อื่น ๆ และ การเพิ่มลงใน GridLayout (ไม่ใช่ GridView นอกจากนี้ GridLayout ยังมีอยู่ใน lib สนับสนุน) TableLayout หรือที่คล้ายกัน
adamp

11
@adamp หากสิ่งนี้ไม่ดีโปรดเพิ่มคำตอบของคุณด้วยทางออกที่ดีที่สุดที่คุณคิดได้
aleb

34

หลังจากใช้คำตอบจาก @tacone และแน่ใจว่าใช้งานได้ฉันตัดสินใจลองย่อรหัส นี่คือผลลัพธ์ของฉัน PS: เทียบเท่ากับการตั้งค่าบูลีน "ขยาย" ในคำตอบของ tacones ให้เป็นจริงเสมอ

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
สิ่งนี้ใช้ได้ดีสำหรับฉัน - ฉันใช้ GridView จำนวนมากใน ListView ไม่แน่ใจว่านั่นเป็นความคิดที่ไม่ถูกต้องหรือไม่ - จำเป็นต้องตรวจสอบประสิทธิภาพด้วยชุดข้อมูลขนาดใหญ่ แต่ไม่ว่าอย่างไรขอบคุณสำหรับรหัส ฉันคิดว่ามีข้อผิดพลาดแบบ off-by-one - ฉันต้องใช้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

ViewGroup.LayoutParams params = gridView.getLayoutParams (); พ่น NullPointerException
Luke Allison

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 จะไม่ทำงาน จำเป็นต้องใช้ Vertical Scroll View อย่างชัดเจน

 @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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.