Chiều cao của Gridview bị cắt


124

Tôi đang cố gắng hiển thị 8 mục trong chế độ xem lưới. Đáng buồn thay, chiều cao của Gridview luôn quá ít, do đó nó chỉ hiển thị hàng đầu tiên, và một phần nhỏ của thứ hai.

Cài đặt android:layout_height="300dp"làm cho nó hoạt động. quấn_ contentfill_parentdường như không.

Chế độ xem lưới của tôi:

<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" />

Tài nguyên vật phẩm của tôi:

<?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>

Vấn đề dường như không liên quan đến việc thiếu không gian dọc.

Tôi có thể làm gì ?


Câu trả lời:


351

Sau khi (quá nhiều) nghiên cứu, tôi vấp phải câu trả lời xuất sắc của Neil Traft .

Thích nghi công việc của mình cho GridViewđã chết dễ dàng.

Có thể mở rộngHeightGridView.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;
    }
}

Bao gồm nó trong bố trí của bạn như thế này:

<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" />

Cuối cùng, bạn chỉ cần yêu cầu nó mở rộng:

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

20
giải pháp này không hiệu quả về bộ nhớ và ứng dụng sẽ bị sập nếu các ô là hình ảnh. Giải pháp này cho biết cuộn xem chiều cao của toàn bộ khung lưới để nó có thể đi xuống, nhưng vấn đề là phải làm như vậy để nó hiển thị mọi thứ mà không cần sử dụng tái chế. Không có m quặng hơn 200 mặt hàng có thể làm việc.
Mariano Latorre

7
@adamp Tôi nghĩ có những trường hợp hữu ích cho việc này. Nếu bạn có số lượng mục giới hạn để hiển thị thành mảng 2d, sử dụng loại GridView này có vẻ dễ hơn là cố gắng tạo một số loại TableLayout tùy chỉnh / động, phải không?
greg7gkb

5
Không hoạt động với tôi, tôi đã đặt ExpandableHeightGridView trong ScrollView, nó cắt góc nhìn cuối cùng.
Chirag Nagariya

3
@tacone Có một số giải pháp tốt hơn cho loại vấn đề này có sẵn trong khung, thư viện hỗ trợ và mã nguồn mở khác trên web, cách dễ nhất có thể là Chế độ xem vòng lặp đơn giản từ bộ điều hợp hoặc ở nơi khác và thêm chúng vào GridLayout, (không phải GridView; GridLayout cũng có sẵn trong lib hỗ trợ) TableLayout hoặc tương tự.
quảng cáo

11
@adamp Nếu điều này không tốt, vui lòng thêm câu trả lời của bạn với giải pháp tốt nhất bạn có thể nghĩ đến
aleb

34

Sau khi sử dụng câu trả lời từ @tacone và đảm bảo nó hoạt động, tôi quyết định thử rút ngắn mã. Đây là kết quả của tôi. PS: Nó tương đương với việc boolean "mở rộng" trong câu trả lời tacones luôn được đặt thành đúng.

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();
    }
}

Nhưng chờ đã - điều này vẫn còn gặp phải vấn đề sử dụng bộ nhớ; bạn không tái chế nữa phải không?
Fattie

6

Một cách tiếp cận tương tự khác có hiệu quả với tôi, là tính chiều cao cho một hàng và sau đó với dữ liệu tĩnh (bạn có thể điều chỉnh nó để phân trang), bạn có thể tính toán số lượng hàng bạn có và thay đổi kích thước chiều cao của GridView một cách dễ dàng.

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

Sử dụng mã này sau khi đặt bộ điều hợp và khi GridView được vẽ hoặc bạn sẽ nhận được height = 0.

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

1
Điều này hoạt động tốt với tôi - Tôi đang sử dụng một loạt GridView bên trong ListView. Không chắc đó có phải là ý tưởng tồi hay không - cần điều tra hiệu suất với một bộ dữ liệu lớn. Nhưng bất kể, cảm ơn cho mã. Tôi nghĩ rằng có một lỗi xảy ra mặc dù - tôi đã phải sử dụngint rows = items / columns + 1;
Andrew

đối với hệ điều hành android 5.0 tôi gặp lỗi nàyjava.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
silverFoxA

Viewgroup.LayoutParams params = GridView.getLayoutParams (); ném một NullPulumException
Luke Allison

4

Tìm thấy tacones trả lời hữu ích ... vì vậy tôi đã chuyển nó sang 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
Kudos anh chàng. Hoạt động tuyệt vời trong xamarin.android
suchith

0

Chỉ cần tính chiều cao cho AT_MOST và đặt thành số đo. Ở đây GridView Scroll sẽ không hoạt động như vậy. Cần sử dụng Xem dọc di chuyển rõ ràng.

 @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);
 }

Phương pháp này có giúp bạn nhận được cuộn cho GridView không
vậy vào
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.