2

I have an activity which contains a ScrollView, and also I have a GridView inside the ScrollView, the layout:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/root">

    <RelativeLayout
            android:padding="10dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        .........
        <com.test.android.view.ScrollableGridView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:numColumns="auto_fit"
                android:columnWidth="100dp"
                android:verticalSpacing="2dp"
                android:focusable="false"
                android:clickable="false">
        </com.test.android.view.ScrollableGridView>
    </RelativeLayout>
</ScrollView>

public class ScrollableGridView extends GridView {
    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}

Why I use the custome gridview is to make sure the gridview can expand to its max height(check this).

Now once the activity loaded, I will load data from the server, then call the:

gridAdapter.notifyDatasetChanged();

Then the activity will scroll to the grid view which means user can not see the content above the gridview.

I have tried that:

mScrollView.scrollTo(0,mScrollView.getBottom());

But it does not work.

Any idea to fix it?

Community
  • 1
  • 1
hguser
  • 35,079
  • 54
  • 159
  • 293

2 Answers2

6

Issue:

GridView is being scrolled automatically.

Reason:

When the screen is loaded, it finds the first focusable View from its ViewHierarchy and sets the focus to that View.

Solution:

You can set focus to some other View so that Android does not focus the GridView at first,so it won't scroll automatically.

Example:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/root">

<RelativeLayout
        android:padding="10dp"
        android:id="@+id/rlContainer"           //you may set id and requestfocus from java code as well
        android:focusable="true"                //add this 
        android:focusableInTouchMode="true"     //add this
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    .........                                     //you can also add focusable,focusableInTouchMode to any other view before the GridView
    <com.test.android.view.ScrollableGridView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:numColumns="auto_fit"
            android:columnWidth="100dp"
            android:verticalSpacing="2dp"
            android:focusable="false"
            android:clickable="false">
    </com.test.android.view.ScrollableGridView>
</RelativeLayout>

From java code,

inside onCreate() method of your Activity

RelativeLayout rlContainer = (RelativeLayout) findViewById(R.id.rlContainer);
rlContainer.requestFocus();
Mehul Joisar
  • 15,348
  • 6
  • 48
  • 57
1

A better option will be to scroll to the GridView's top. Also, you should post the scrollTo(int, int) call:

mScrollView.post(new Runnable() {
    @Override
    public void run() {
        mScrollView.scrollTo(0, mGridView.getTop());
    }
});

Edit:

So, from what I can gather:

  • on first load, GridView is at the top & visible

  • then, you load some data from the server

  • some layout container above the GridView is updated with data - this increases the layout's size and the GridView is pushed down

Lets say that the layout container above the GridView is mLayoutContainer. After adding data to this container, add a OnPreDrawListener to it:

mLayoutContainer.getViewTreeObserver().addOnPreDrawListener(
                             new ViewTreeObserver.OnPreDrawListener() {
    @Override
    public boolean onPreDraw() {
        // remove the OnPreDrawListener
        mLayoutContainer.getViewTreeObserver().removeOnPreDrawListener(this);

        // update scrollY for the ScrollView
        // since mLayoutContainer is about to be drawn, its height 
        // is available. 
        mScrollView.setScrollY(mScrollView.getScrollY() 
                                      + mLayoutContainer.getHeight());

        // we're allowing the current draw pass
        return true;
    }
});

This is basically a state-restore operation. We are asserting that prior state was perfect - state changed resulting in the GridView being pushed down - counter state change by scrolling ScrollView by an equal amount.

Vikram
  • 51,313
  • 11
  • 93
  • 122
  • In fact this is what I tried to avoid, since the grid view will scroll to its top automatically. I do not want the gird view scroll at all. – hguser Aug 22 '14 at 08:38
  • @hguser I am not suggesting that you scroll the `GridView`. The code above scrolls the `ScrollView` to `GridView's` top. – Vikram Aug 22 '14 at 08:42
  • I think we should scroll `ScrollView` to the `ScrollView's` top, isn't it? – hguser Aug 22 '14 at 09:10
  • @hguser It would really help if you could post a video of the problem you are facing. I think (in this case especially), a video would get you the right answer fast. It might just be me, but I'm finding it hard to visualize the issue. My apologies if this is inconvenient. – Vikram Aug 22 '14 at 09:25
  • 1
    Fine, I will make a gif of the screenshot. You are welcome. :) – hguser Aug 22 '14 at 09:28
  • @hguser Thank you! So, the problem is - when the user clicks `Check the detail of the item`, gridview is shown but is quickly scrolled off screen because data is loaded above it? And you want the gridview to stay where it is on first load - and if the user wants to see the details(data loaded asynchronously), s/he will have to scroll up? – Vikram Aug 22 '14 at 09:55
  • Yes, "want the gridview to stay whre it is on the first load", exactly what I want! – hguser Aug 22 '14 at 09:56
  • @hguser I have added an `Edit` to my answer. See if it helps any. – Vikram Aug 22 '14 at 13:19
  • Hi, thanks for your update, I have not tried yet, but from the code `mScrollView.setScrollY(mScrollView.getScrollY() + mLayoutContainer.getHeight());` it seems that you try to scroll the view to make the gridview visible? – hguser Aug 23 '14 at 02:40
  • @hguser: I have posted an answer. I hope it will solve your issue. – Mehul Joisar Aug 28 '14 at 13:16