Dilip
Dilip

Reputation: 2311

How to put GridView inside ScrollView

I have to design layout such that whole layout should scroll and inside layout I have to display related content in Grid form so I decided to use GridView.But problem is that I’m unable to use GridView inside ScrollView I have read documentation(Documentation also saying that we should not use GridView inside ScrollView) also.But I have to do this,so can any please give me some idea about this.Thanks

Upvotes: 70

Views: 84164

Answers (11)

Vijaykanth Reddy
Vijaykanth Reddy

Reputation: 11

Trust this solution worked for me!

android:nestedScrollingEnabled="true"

The code above inside grid view enables to scroll gridview and set width and height android:layout_width="match_parent" android:layout_height="200sp"

This will work even inside scrollview Thanks for the previous answers I figured out this for the previous answers. Thanks to them

Upvotes: 1

Stephen Emery
Stephen Emery

Reputation: 327

I was also trying to make a GridView scrollable inside a NestedScrollView.

This answer on another question helped me: https://stackoverflow.com/a/38612612

Enable your GridView Property as

android:nestedScrollingEnabled="true"

Original poster: Droid_Dev

Upvotes: 11

CoolMind
CoolMind

Reputation: 28793

If you want to have GridView inside ScrollView / RecyclerView, there are 2 cases:

  1. If you want to have GridView with all rows visible, see https://stackoverflow.com/a/63724794/2914140.

  2. If you want to have one row visible in GridView, but be able to scroll it (to reveal other rows), see https://stackoverflow.com/a/26852498/2914140.

Upvotes: 0

Lionel T.
Lionel T.

Reputation: 1224

I found a way to give the GridView a fixed size inside ScrollView, and enable scrolling it. That allows you to see the entire ScrollView without having to scroll all elements of the GridView, and it makes more sense to me that using an ExpandableHeightGridView.

To do so, you would have to implement a new class extending GridView and override onTouchEvent() to call requestDisallowInterceptTouchEvent(true). Thus, the parent view will leave the Grid intercept touch events.

GridViewScrollable.java:

package com.example;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.GridView;

public class GridViewScrollable extends GridView {

    public GridViewAdjuntos(Context context) {
        super(context);
    }

    public GridViewAdjuntos(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent ev){
        // Called when a child does not want this parent and its ancestors to intercept touch events.
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(ev);
    }
}

Add it in your layout with the characteristics and margins you want, inside a ScrollView:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:isScrollContainer="true" >

    <com.example.GridViewScrollable
    android:id="@+id/myGVS"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:numColumns="auto_fit"
    android:stretchMode="columnWidth" />

</ScrollView>

And just get it in your activity:

GridViewScrollable myGridView = (GridViewScrollable) findViewById(R.id.myGVS);

I hope it helps =)

In Kotlin:

class GridViewScrollable @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : GridView(context, attrs, defStyleAttr) {

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        // Called when a child does not want this parent and its ancestors to intercept touch events.
        requestDisallowInterceptTouchEvent(true)
        return super.onTouchEvent(ev)
    }
}

There is an annoying warning: "Custom view GridViewScrollable overrides onTouchEvent but not performClick". Please, resolve yourself if you want.

Upvotes: 10

Abdurrhman Sefer
Abdurrhman Sefer

Reputation: 25

 gridView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    v.getParent().requestDisallowInterceptTouchEvent(true);
                    return false;
                }

            });

// Setting on Touch Listener for handling the touch inside ScrollView

Upvotes: 0

Kishore Reddy
Kishore Reddy

Reputation: 2454

It's better to use ExpandableHeightlistView or ExpandableHeightGridView inside scrollview.

Logic

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.

int expandSpec = MeasureSpec.makeMeasureSpec(
 Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
 super.onMeasure(widthMeasureSpec, expandSpec);

 ViewGroup.LayoutParams params = getLayoutParams();
 params.height = getMeasuredHeight();

for further information explore the example below with demo

http://www.londatiga.net/it/programming/android/make-android-listview-gridview-expandable-inside-scrollview/

Upvotes: 1

j2emanue
j2emanue

Reputation: 62519

i would not force the issue. GridView does not work well in a scrollView. instead convert your gridview into a recyclerview and use a gridLayoutManager to resolve the issue.

Upvotes: 1

Vikram Gupta
Vikram Gupta

Reputation: 6516

I know I'm late but I have another solution which I must share and which works flawlessly. Here, the method calculates the GridView height based on the number of items it contains and sets the height to the GridView at run time.

public void setGridViewHeightBasedOnChildren(GridView gridView, int columns) {
        ListAdapter listAdapter = gridView.getAdapter(); 
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        int items = listAdapter.getCount();
        int rows = 0;

        View listItem = listAdapter.getView(0, null, gridView);
        listItem.measure(0, 0);
        totalHeight = listItem.getMeasuredHeight();

        float x = 1;
        if( items > columns ){
            x = items/columns;
            rows = (int) (x + 1);
            totalHeight *= rows;
        }

        ViewGroup.LayoutParams params = gridView.getLayoutParams();
        params.height = totalHeight;
        gridView.setLayoutParams(params);

}

After you have called setAdapter on your gridview, just call

setGridViewHeightBasedOnChildren( <yourGridView> , <no of grid view columns> )

and it'll work.

You can the define the gridview in your xml as you normally do

and let the code take care of it. :)

Upvotes: 36

aidan sliney
aidan sliney

Reputation: 21

If you have used dennisdrew's answer and you have content above your grid and it gets hidden when you open your view simply add the last line below

ExpandableHeightGridView gridView = (ExpandableHeightGridView) findViewById(R.id.myId);
gridView.setAdapter(yourAdapter);
gridView.setExpanded(true);
gridView.setFocusable(false);

Upvotes: 2

Dharmendra Chaudhary
Dharmendra Chaudhary

Reputation: 267

To use gridview inside scrollview, set scrollview android:fillViewport="true"

I know its late to answer here but may be useful to some new developers.

Upvotes: 6

dennisdrew
dennisdrew

Reputation: 4399

There are definitely benefits to a GridView beside the inherent scrolling. For example, a consistent, dynamic layout of cells that will expand and contract based on the data you pass into it. So, when people say it's not good to desire such a functionality, I think that's wrong because you could want the dynamic grid of images (views) inside of a scrolling view, but want that entire scrolling view to contain other things than just the grid cells.

Now, here is how you can do this. Check the answer here. It is an expandable height GridView, which you will want to import / create in your project. What that basically means is that as more items are added to the GridView, it will just expand its height, as opposed to keeping its height set and using scrolling. This is exactly what you want.

Once you have the ExpandableHeightGridView in your project, go to your XML layout where you want the GridView to be. You can then do something like this (paraphrasing):

<ScrollView ...>
    <RelativeLayout ...>
        <com.example.ExpandableHeightGridView ... />
        <other view items />
    </RelativeLayout>
</ScrollView>

Then, in your activity where you set the GridView's adapter, you want to make sure you set it to expand. So:

ExpandableHeightGridView gridView = (ExpandableHeightGridView) findViewById(R.id.myId);
gridView.setAdapter(yourAdapter);
gridView.setExpanded(true);

The reason you want this expandable GridView is because, the fact that a standard GridView doesn't expand is what causes it to scroll. It sticks to a certain height, and then as more items fill it past its view bounds, it becomes scrollable. Now, with this, your GridView will always expand its height to fit the content within it, thus never allowing it to enter its scrolling mode. This enables you to use it inside of the ScrollView and use other view elements above or below it within the ScrollView, and have them all scroll.

This should give you the result you're looking for. Let me know if you have any questions.

Upvotes: 118

Related Questions