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 to
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 =)
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
If you want to scroll it to top/bottom programmatically, you can do this(it's from here):
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);
}
});
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
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>
Simply add this line of code in the Child of ScrollView
android:focusableInTouchMode="true"