Android ScrollView doesn't start at top, but at the beginning of the GridView

JavaAndroidGridviewScrollview

Java Problem Overview


I have a problem with a ScrollView that has inside of it a personalized GridView and other tipe of views.The first time I start the Activity, the ScrollView starts at its top, but if I visit the Activity other times the ScrollView starts at the beginning of the GridView.I used the class ExpandableHeightGridView found in this link for my GridView. The xml code for the Activity layout is this one:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scrollViewLuogo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff" >
    
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff" >

    <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="150dp"
            android:layout_height="100dp"
            android:layout_marginLeft="14dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:adjustViewBounds="true"
            android:maxHeight="200dp"
            android:maxWidth="200dp"
            android:scaleType="fitXY"
            android:src="@android:drawable/ic_menu_gallery" />

        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/nomeTVActivityLuogo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textStyle="bold"
                android:textSize="17sp"
                android:textColor="#005788" />

            <TextView
                android:id="@+id/indirizzoTVActivityLuogo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/linearLayout2"
        android:layout_marginTop="10dp"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/imageViewMappaLuogo"
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="14dp"
            android:layout_marginRight="14dp"
            android:layout_marginTop="5dp"
            android:scaleType="fitXY"
            android:src="@drawable/sfondo_mappa" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:text="Immagini"
            android:textColor="#97d6f9" />

        <View
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:layout_marginLeft="14dp"
            android:layout_marginRight="14dp"
            android:layout_marginTop="5dp"
            android:background="#97d6f9" />

        <com.example.mappine.ExpandableHeightGridView
            android:id="@+id/gridViewLuogo"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:numColumns="3" >
        </com.example.mappine.ExpandableHeightGridView>

    </LinearLayout>

</RelativeLayout>

I've tried using the code scrollView.fullScroll(ScrollView.FOCUS_UP); but it didn't work.And even with scrollView.scrollTo(0, 0); I didn't have success. The only code that worked was:

    scrollView.post(new Runnable() 
      { 
         public void run() { 
             scrollViewLuogo.fullScroll(ScrollView.FOCUS_UP); 
         } 
      });

but it makes a fast animation from the top of the GridView to the top of the screen and i don't like it.

Any suggestion??

Java Solutions


Solution 1 - Java

Solution:

Ok sorry if it is a late reply but I stumbled upon the same issue (only that I was using ListView instead) and with a bit of trial and error I found the solution to this:

Basically the problem lies in the fact that the GridView/ListView child automatically requests parent focus (ScrollView) when you "hack" and resize its content with ExpandableHeightGridView, which happens after layout is rendered, and hence you see that animation when trying to scroll it up with scrollTo() (happens AFTER layout is created and AFTER gridView is resized so any generic callback is useless to handle this programatically).

So then, the simplest solution I found was to simply disable focusable property on the ListView/GridView with:

listView.setFocusable(false);

That way when you first enter the activity, focus will default and not rely on Listview/GridView.

And all working fine =)

Solution 2 - Java

The easiest way is to add on the parent ScrollView the following xml attributes:

android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"

That means that the ScrollView as a whole will be the one getting focus instead of any inner container when you launch the activity. This is also useful, for example, when you have an edit text inside your layout and you don't want it to get focus immediately and popup the keyboard when entering a screen (It's the same principle).

So, your ScrollView on top of your layout would look like this:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scrollViewLuogo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="beforeDescendants"
    android:focusableInTouchMode="true"
    android:background="#fff" >

Solution 3 - Java

Simply add this line of code in the Child of ScrollView

android:focusableInTouchMode="true"

Solution 4 - Java

Simply add this two line in your parent layout

android:focusable ="true" android:focusableInTouchMode ="true"

Try this, Hope it will work for you

Solution 5 - Java

If you want to scroll it to top/bottom programmatically, you can do this(it's from https://stackoverflow.com/a/14897780/3077508">here</a>;):

For Focus to Down:

((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() { 
    public void run() { 
        ((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_DOWN); 
    } 
});

For Focus to Top

((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() { 
    public void run() { 
        ((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_UP); 
    } 
});

Solution 6 - Java

ScrollView

android:fitsSystemWindows="false"

Solution 7 - Java

Sadly the example you followed is extremely poor. ListViews and GridViews should never be placed into ScrollViews.

ScrollView's purpose is to give infinite height to its child view. List/GridView's purpose is to take a potentially very large data set and only generate enough item views to fill the space made available to it at a time for efficiency. Both are capable of scrolling their content without the other.

Putting a List/GridView in a ScrollView is saying, "unstoppable force, meet immovable object." Either you've defeated the point of List/GridView or you've defeated the point of ScrollView by combining them.

Better ways to include other content within the same scrolling region include using header/footer views with a ListView, or otherwise concatenating the contents of list adapters together into a single adapter. Creating ListView items that contain several items per row to form a grid for part of an adapter's content is straightforward.

Solution 8 - Java

Simple way to achieve this is to set up an ID to your ScrollView in XML ... let's say

scrollView_main

After that you just need to go to your java file and declare it like a normal variable above the procedure onCreate to be a global one like this

ScrollView scrollView_main;

ok, now is time to go to onCreate procedure and declare this, to get connection with your ID from XML file

scrollView_main = (ScrollView)findViewById(R.id.scrollView_main);

and finally the code that will do the trick for your ScrollView to be scrolled on top, this is your answer

scrollView_main.smoothScrollTo(0,0); //set it on top

Solution 9 - Java

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 =)

Solution 10 - Java

As a follow-up I'll share my pain as well. In my app I have a RecyclerView inside a NestedScrollView inside a CoordinatorLayout:

<CoordinatorLayout>
  <NestedScrollView id="@+id/content">
     
     .......

     <TextView android:id="@+id/header"/>

     <RecyclerView android:id="@+id/recyclerView"/>       
  
  </NestedScrollView>
</CoordinatorLayout>
  

Of course upon opening the activity, the page scrolled to include the recyclerView in the middle. None of the answers above worked, so I came up with the following solution:

@Override
protected void onCreate( Bundle savedInstanceState ) {
  ....
  content.setOnScrollChangeListener( new NestedScrollView.OnScrollChangeListener() {
    @Override
    public void onScrollChange( NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY ) {
      Rect scrollBounds = new Rect();
      v.getHitRect( scrollBounds );
      if( header.getLocalVisibleRect( scrollBounds ) ){
        if( View.VISIBLE != recyclerView.getVisibility() ){
          recyclerView.setVisibility( View.VISIBLE );
          fillRecyclerViewSomehow();
        }
      }
    }
  }
}

@Override
protected void onResume() {
  ...
  recyclerView.setVisibility( View.GONE ); // this effectively suppresses the focusability
}

HTH

Solution 11 - Java

If nothing works, just put this as the first element of your scrollView's single child:

<EditText
   android:layout_width="0dp"
   android:layout_height="0dp"/>

example:

  <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            <EditText
                    android:layout_width="0dp"
                    android:layout_height="0dp"/>
            <!-- your other views  -->
        </LinearLayout>
</ScrollView>

Solution 12 - Java

I had a similar issue and something totally different worked for me. I had the following sort of view hierarchy -

<LinearLayout>
    <ImageView />
    <ScrollView>
        <TextView android:id="header_tv"/>
        <TabLayout />
        <ViewPager2 />
    </ScrollView>
</LinearLayout>

And the view used to open already scrolled till the view pager. I simply added android:focusable="true" to the first element of scroll view to fix this, as follows -

<LinearLayout>
    <ImageView />
    <ScrollView>
        <TextView 
            android:id="header_tv"
            android:focusable="true" />
        <TabLayout />
        <ViewPager2 />
    </ScrollView>
</LinearLayout>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2328149View Question on Stackoverflow
Solution 1 - JavaSuppressWarningsView Answer on Stackoverflow
Solution 2 - JavaDisruptionView Answer on Stackoverflow
Solution 3 - JavaBilal AhmadView Answer on Stackoverflow
Solution 4 - JavaSaurabh GaddelpalliwarView Answer on Stackoverflow
Solution 5 - JavaPiasyView Answer on Stackoverflow
Solution 6 - JavaMatheus MarquesView Answer on Stackoverflow
Solution 7 - JavaadampView Answer on Stackoverflow
Solution 8 - JavaCristian BabarusiView Answer on Stackoverflow
Solution 9 - JavaLionel T.View Answer on Stackoverflow
Solution 10 - JavainjecteerView Answer on Stackoverflow
Solution 11 - JavaKishita VariyaView Answer on Stackoverflow
Solution 12 - JavaRishabh SharmaView Answer on Stackoverflow