Android ScrollView does not start at the top, but at the beginning of the GridView

I have a problem with ScrollView, inside of which there is a personalized GridView and another type of views. The first time I start an Activity, the ScrollView starts from the top, but if I visit the Activity again, the ScrollView starts at the beginning of the GridView. I used the ExpandableHeightGridView class found in this link for my GridView. Xml code for Activity layout:

<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 tried using the code scrollView.fullScroll(ScrollView.FOCUS_UP); but it did not work. And even with scrollView.scrollTo(0, 0); I have not had success. The only code executed:

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

but it does a quick animation from the top of the GridView at the top of the screen, and I don't like it.

Any suggestion

+52
java android gridview scrollview
Jun 02 '13 at 18:45
source share
11 answers

Decision:

Well, if this is a late answer, but I came across the same problem (only that I used ListView instead), and with a bit of trial and error, I found a solution for this:

The main problem is that the child of the GridView / ListView automatically asks for the parent focus (ScrollView) when you β€œcrack” and resize it using the ExpandableHeightGridView, which happens after the layout is rendered, and therefore you see this animation when you try to scroll it with scrollTo () (AFTER is created, and the AFTER gridView changes, so any general callback is useless to handle this programmatically).

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

 listView.setFocusable(false); 

Thus, when you first enter an action, the focus will be by default and will not rely on Listview / GridView.

And everything works fine =)

+165
Jan 20 '14 at 13:14
source share

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

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

This means that ScrollView as a whole will receive focus instead of any internal container when the operation starts. This is also useful, for example, when you have editing text inside your layout and you don’t want it to immediately get focus and pop up the keyboard when you enter the screen (this is the same principle).

So, your ScrollView on top of the layout will 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" > 
+21
Sep 30 '15 at 9:31
source share

Just add two lines to the parent layout

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

Try this, hope this works for you.

+5
Jun 28 '17 at 8:36
source share

Just add this line of code to Child of ScrollView

 android:focusableInTouchMode="true" 
+4
Oct 27 '17 at 9:49 on
source share

If you want to scroll it to the top / bottom programmatically, you can do this ( from here ):

For focus down:

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

For focus up

 ((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() { public void run() { ((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_UP); } }); 
+3
Nov 22 '14 at 8:44
source share

Scrollview

 android:fitsSystemWindows="false" 
+3
Dec 28 '16 at 19:08
source share

Unfortunately, the example you provided is extremely low. ListViews and GridViews should never fit in ScrollViews.

ScrollView's goal is to provide infinite height to its child view. The goal of a List / GridView is to use a potentially very large dataset and only create enough items to fill the space available to it at a time to increase efficiency. Both can scroll through their contents without the other.

Inserting a list / GridView in ScrollView says, "Impossible force, meet a fixed object." Either you defeated the List / GridView point, or you defeated the ScrollView point by combining them.

More effective ways to include other content within the same scroll pane include using the header / footer views using the ListView or combining the contents of list adapters together into one adapter. Creating ListView items that contain multiple items in a row to form a grid for part of the contents of the adapter is simple.

+2
Jun 02 '13 at 19:50
source share

I found a way to provide a GridView with a fixed size inside a ScrollView and enable scrolling . This allows you to see the entire ScrollView without having to scroll through all the GridView elements, and for me it makes more sense to use ExpandableHeightGridView.

To do this, you will need to implement a new class that extends the GridView and overrides onTouchEvent () to call requestDisallowInterceptTouchEvent (true). Thus, the parent view will leave the mesh interception 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 to your layout with the characteristics and fields you want inside the 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 this helps =)

0
Nov 11 '14 at 15:41
source share

As a continuation, I will also share my pain. In my application, 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, when you open an activity, the page scrolls to enable 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 } 

NTN

0
Apr 19 '16 at 9:30
source share

An easy way to achieve this is to set the id for your ScrollView in XML ... let's say

 scrollView_main 

After that, you just need to go to your Java file and declare it as a regular variable on the onCreate procedure so that it is global, like this

 ScrollView scrollView_main; 

ok, now it's time to go to the onCreate procedure and declare this to get the connection to your id from the XML file

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

and finally, the code that helps you to scroll the scrollview on top is your answer

 scrollView_main.smoothScrollTo(0,0); //set it on top 
0
Aug 20 '18 at 15:47
source share

If nothing works, just put this as the first element of your scrollView 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> 
0
Jul 16 '19 at 10:38
source share



All Articles