Skip to content Skip to sidebar Skip to footer

How To Add Multiple Gridviews To A Scrollview In Android Java?

I'm trying to add multiple gridviews to a scrollview in linear layout at runtime. But only first row displays. Pls help

Solution 1:

You can't nest scrollable Views in Android - i.e. ListView, GridView, ScrollView.

You could give a look at the following code:

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.GridView;

publicclassScrollableGridViewextendsGridView {
    booleanexpanded=true;

    publicScrollableGridView(Context context)
    {
        super(context);
    }

    publicScrollableGridView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

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

    publicbooleanisExpanded()
    {
        return expanded;
    }


    @OverridepublicvoidonMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // HACK! TAKE THAT ANDROID!if (isExpanded())
        {
            // Calculate entire height by providing a very large height hint.// But do not use the highest 2 bits of this integer; those are// reserved for the MeasureSpec mode.intexpandSpec= MeasureSpec.makeMeasureSpec(
                    Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);

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

    publicvoidsetExpanded(boolean expanded)
    {
        this.expanded = expanded;
    }
}

It is a little better version of GridView allowing it to almost work when nested in ScrollView. I said "almost work" since I found it sometimes being 20-30 pixels too short or too long. You should note that this would prevent the views from being reuse, so it is way heavier than normal GridView.

In my case I ended up extending LinearLayout and using it to align its children in columns. It wasn't really hard - I can give you examples if you want. :)

I got the GridView example from this answer.

Here is an example for a GridView based on LinearLayout:

import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

publicclassGridLikeLayoutextendsLinearLayout {
    privatestaticfinalintDEFAULT_ITEMS_PER_ROW=1;
    privatefinalintDEFAULT_COLUMN_WIDTH= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, 150, getContext().getResources()
                    .getDisplayMetrics());

    privateintitemsPerRow= DEFAULT_ITEMS_PER_ROW;
    private List<View> innerViews = null;

    privateint columnWidth;

    publicGridLikeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArraya= context.obtainStyledAttributes(attrs,
                R.styleable.GridLikeLayout);

        // itemsPerRow = a.getInt( R.styleable.GridLikeLayout_columns,// DEFAULT_ITEMS_PER_ROW);try {
            columnWidth = (int) a.getDimension(
                    R.styleable.GridLikeLayout_column_width, DEFAULT_COLUMN_WIDTH);
        } catch (UnsupportedOperationException uoe) {
            columnWidth = (int) a.getInt(
                    R.styleable.GridLikeLayout_column_width, DEFAULT_COLUMN_WIDTH);
        }

        setOrientation(LinearLayout.VERTICAL);
    }

    publicGridLikeLayout(Context context) {
        super(context);
        setOrientation(LinearLayout.VERTICAL);
    }

    publicvoidsetInnerViews(List<View> innerViews) {
        this.innerViews = innerViews;
        processViews();
    }

    public List<View> getInnerViews() {
        return innerViews;
    }

    protectedvoidprocessViews() {
        if (null != innerViews) {
            LinearLayoutinnerContainer=null;
            innerContainer = generateInnerContainer();
            intchildrenCount= innerViews.size();
            for (intindex=0; index < childrenCount; ++index) {
                if (isFull(innerContainer)) {
                    addInnerContainer(innerContainer);
                    innerContainer = generateInnerContainer();
                }
                Viewchild= innerViews.get(index);
                if (null != child.getParent()) {
                    ((ViewGroup) child.getParent()).removeView(child);
                }
                addInnerView(innerContainer, child);
            }

            addInnerContainer(innerContainer);
        }
    }

    protectedbooleanisFull(LinearLayout innerContainer) {
        return0 == (innerContainer.getChildCount() % itemsPerRow)
                && 0 < innerContainer.getChildCount();
    }

    protectedvoidaddInnerView(LinearLayout innerContainer, View child) {
        intwidth= LayoutParams.WRAP_CONTENT;
        intheight= LayoutParams.WRAP_CONTENT;
        LayoutParamsinnerParams=newLayoutParams(width, height);
        innerParams.weight = 1;
        innerParams.gravity = Gravity.CENTER;
        innerContainer.addView(child, innerParams);
    }

    protectedvoidaddInnerContainer(LinearLayout innerContainer) {
        LayoutParamsparams= generateDefaultLayoutParams();
        params.width = LayoutParams.MATCH_PARENT;
        addView(innerContainer, params);
    }

    protected LinearLayout generateInnerContainer() {
        LinearLayout innerContainer;
        innerContainer = newLinearLayout(getContext());
        innerContainer.setGravity(Gravity.CENTER);
        return innerContainer;
    }

    publicvoidsetOnInnerViewClickListener(OnClickListener listener) {
        for (View innerView : innerViews) {
            innerView.setOnClickListener(listener);
        }
    }

    @OverrideprotectedvoidonMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Sets up mListPaddingsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);

        intwidthMode= MeasureSpec.getMode(widthMeasureSpec);
        intwidthSize= MeasureSpec.getSize(widthMeasureSpec);

        if (widthMode == MeasureSpec.UNSPECIFIED) {
            if (columnWidth > 0) {
                widthSize = columnWidth + getPaddingLeft() + getPaddingRight();
            } else {
                widthSize = getPaddingLeft() + getPaddingRight();
            }
            widthSize += getVerticalScrollbarWidth();
        }

        intchildWidth= widthSize - getPaddingLeft() - getPaddingRight();
        intcolumnsNumber= determineColumns(childWidth);
        if (columnsNumber > 0 && columnsNumber != itemsPerRow) {
            itemsPerRow = columnsNumber;
            removeAllViews();
            processViews();
        }
    }

    protectedintdetermineColumns(int availableSpace) {
        intcolumnsNumber= itemsPerRow;
        if (0 < columnWidth) {
            columnsNumber = availableSpace / columnWidth;
        } 
        return columnsNumber;
    }

}

Here is my resource file for the custom attributes:

<?xml version="1.0" encoding="utf-8"?><resources><attrname="column_width"format="dimension|integer"><enumname="single_column"value="-1" /></attr><declare-styleablename="GridLikeLayout"><attrname="column_width" /></declare-styleable></resources>

Here is an example usage:

<?xml version="1.0" encoding="utf-8"?><FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/layoutContainer"android:layout_width="fill_parent"android:layout_height="fill_parent" ><ScrollViewandroid:id="@+id/itemsScroller"android:layout_width="fill_parent"android:layout_height="fill_parent" ><LinearLayoutandroid:id="@+id/itemsLayout"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="vertical" ><your_package.view.GridLikeLayoutxmlns:my="YOUR APPLICATION PACKAGE"android:id="@+id/MyGrid"android:layout_width="fill_parent"android:layout_height="wrap_content"my:column_width="260dp"android:focusable="true"android:gravity="center_horizontal"android:padding="5dp" ></your_package.GridLikeLayout><Viewandroid:id="@+id/viewSeparator"android:layout_width="fill_parent"android:layout_height="2dp" /><your_package.GridLikeLayoutxmlns:my="YOUR APPLICATION PACKAGE"android:id="@+id/list"android:layout_width="match_parent"android:layout_height="wrap_content"my:column_width="single_column" ></your_package.GridLikeLayout></LinearLayout></ScrollView></FrameLayout>

Please tell me if you have any troubles running the example - I'm not able to try it at the moment. So if you have issues, I'll check it up later. Don't forget to change the package names - "your_package" should be the the package where you store the GridLikeLayout and "YOUR APPLICATION PACKAGE" is your app's package - the one specified in the application manifest. :)

Solution 2:

Until you put here the layout I could suppose only that you have set wrong horizontal/vertical parameter in your linear layout.

Solution 3:

Your first solution does work but does not take into account that GridViews often imply image caching such as in my case. Here your first solution leads to OutOfMemoryError every time I start to scroll. Has anybody already got an example solution which does take into account image caching?

Post a Comment for "How To Add Multiple Gridviews To A Scrollview In Android Java?"