Висота Gridview зменшується


124

Я намагаюся відобразити 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

Після (занадто багато) досліджень я натрапив на чудову відповідь Ніла Трафта .

Адаптація його роботи до 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 предметів.
Маріано Латорре

7
@adamp Я думаю, що для цього є корисні випадки. Якщо у вас є обмежена кількість елементів для відображення у двовимірному масиві, використовувати цей тип GridView здається простіше, ніж намагатися створити якусь власну / динамічну таблицю, ні?
greg7gkb

5
Не працює для мене, я помістив ExpandableHeightGridView під ScrollView, він скорочує останній вигляд.
Chirag Nagariya

3
@tacone Існує ряд кращих рішень для подібних проблем, доступних у рамках, бібліотеці підтримки та іншому відкритому вихідному коді в Інтернеті, найпростішим з яких може бути просте витягування поглядів з циклу з адаптера чи в іншому місці та додавши їх до GridLayout (не GridView; GridLayout також доступний у вкладці підтримки) TableLayout або подібного.
adamp

11
@adamp Якщо це не добре, будь ласка, додайте свою відповідь найкращим рішенням, яке ви можете придумати
aleb

34

Після використання відповіді від @tacone і переконавшись, що вона працює, я вирішив спробувати скоротити код. Це мій результат. PS: Це еквівалент того, що булева "розширена" в tacones відповіді завжди встановлена ​​на 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
Це добре працювало для мене - я використовую купу GridViews всередині ListView. Не впевнений, чи це ще погана ідея чи ні - потрібно вивчити ефективність із великим набором даних. Але незалежно, дякую за код. Я думаю, що існує помилка по одному - я повинен був використатиint rows = items / columns + 1;
Ендрю

для нижче 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
Люк Еллісон

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

0

Просто обчисліть висоту для AT_MOST і встановіть на міру. Тут прокрутка GridView не буде працювати. Потрібно чітко використовувати перегляд вертикальної прокрутки.

 @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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.