Detectar final de ScrollView

Tengo una aplicación, que tiene una actividad que utiliza un ScrollView . Necesito detectar cuando el usuario llega a la parte inferior de ScrollView . Hice algunos googleing y encontré esta página donde se explica. Pero, en el ejemplo, que los chicos extiende ScrollView . Como dije, necesito extender la Actividad.

Por lo tanto, me dijo "ok, vamos a tratar de hacer una clase personalizada extender ScrollView , sobreescribir el método onScrollChanged() , detectar el final del rollo, y actuar en consecuencia".

Lo hice, pero en esta línea:

 scroll = (ScrollViewExt) findViewById(R.id.scrollView1); 

Lanza una java.lang.ClassCastException . He cambiado las etiquetas <ScrollView> en mi XML, pero, obviamente, no funciona. Mis preguntas son: ¿Por qué, si ScrollViewExt extiende ScrollView , lanza a mi cara una ClassCastException ? ¿Hay alguna forma de detectar el final del desplazamiento sin tener que hacer demasiadas cosas?

Gracias a la gente.

EDIT: Como prometido, aquí está la pieza de mi XML que importa:

 <ScrollView android:id="@+id/scrollView1" android:layout_width="match_parent" android:layout_height="match_parent" > <WebView android:id="@+id/textterms" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:textColor="@android:color/black" /> </ScrollView> 

Lo cambié de TextView a WebView para poder justificar el texto dentro. Lo que quiero lograr es el botón "Aceptar botón no se activa hasta que los términos del contrato se leen completamente" cosa. Mi clase extendida se llama ScrollViewEx t. Si cambio la etiqueta ScrollView para ScrollViewExt lanza una

 android.view.InflateException: Binary XML file line #44: Error inflating class ScrollViewExt 

Porque no entiende la etiqueta ScrollViewEx . No creo que tenga una solución …

¡Gracias por tus respuestas!

¡Lo hizo!

Aparte de la corrección Alexandre amablemente proporcionarme, tuve que crear una interfaz:

 public interface ScrollViewListener { void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy); } 

Entonces, tuve que anular el método OnScrollChanged de ScrollView en mi ScrollViewExt:

 public class ScrollViewExt extends ScrollView { private ScrollViewListener scrollViewListener = null; public ScrollViewExt(Context context) { super(context); } public ScrollViewExt(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public ScrollViewExt(Context context, AttributeSet attrs) { super(context, attrs); } public void setScrollViewListener(ScrollViewListener scrollViewListener) { this.scrollViewListener = scrollViewListener; } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (scrollViewListener != null) { scrollViewListener.onScrollChanged(this, l, t, oldl, oldt); } } } 

Ahora, como dijo Alexandre, poner el nombre del paquete en la etiqueta XML (mi culpa), hacer mi clase de actividad implementar la interfaz creada antes, y luego, ponerlo todo junto:

 scroll = (ScrollViewExt) findViewById(R.id.scrollView1); scroll.setScrollViewListener(this); 

Y en el método OnScrollChanged, desde la interfaz …

 @Override public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) { // We take the last son in the scrollview View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1); int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY())); // if diff is zero, then the bottom has been reached if (diff == 0) { // do stuff } } 

¡Y funcionó!

Muchas gracias por su ayuda, Alexandre!

Fustigador respuesta fue grande, pero encontré algún dispositivo (Al igual que Samsung Galaxy Note V) no puede llegar a 0, tienen 2 puntos a la izquierda, después del cálculo. Sugiero añadir un poco de amortiguación como a continuación:

 @Override public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) { // We take the last son in the scrollview View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1); int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY())); // if diff is zero, then the bottom has been reached if (diff <= 10) { // do stuff } } 

Encontré una forma sencilla de detectar esto:

 scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { if (scrollView != null) { if (scrollView.getChildAt(0).getBottom() <= (scrollView.getHeight() + scrollView.getScrollY())) { //scroll view is at bottom } else { //scroll view is not at bottom } } } }); 
  • No necesita ScrollView personalizado.
  • Scrollview puede alojar solamente un hijo directo, así que scrollView.getChildAt (0) está bien.
  • Esta solución es correcta incluso la altura de la vista directa de secundaria de scroll es match_parent o wrap_content .

EDITAR

Con el contenido de su XML, puedo ver que usted utiliza un ScrollView. Si desea utilizar su vista personalizada, debe escribir com.your.packagename.ScrollViewExt y podrá utilizarla en su código.

 <com.your.packagename.ScrollViewExt android:id="@+id/scrollView1" android:layout_width="match_parent" android:layout_height="match_parent" > <WebView android:id="@+id/textterms" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:textColor="@android:color/black" /> </com.your.packagename.ScrollViewExt> 

EDIT FIN

¿Podría publicar el contenido xml?

Pienso que usted podría agregar simplemente un oyente de la voluta y comprobar si el último artículo demostrado es el más lastest del listview como:

 mListView.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub if(view.getLastVisiblePosition()==(totalItemCount-1)){ //dosomething } } }); 

Puede utilizar el NestedScrollView la biblioteca de NestedScrollView y su interfaz NestedScrollView.OnScrollChangeListener .

https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html

Si su aplicación tiene como objetivo API 23 o superior, puede utilizar el siguiente método en ScrollView :

 View.setOnScrollChangeListener(OnScrollChangeListener listener) 

Luego siga el ejemplo que @Fusstigador describió en su respuesta. Sin embargo, como se describe en @Will, debe considerar agregar un pequeño buffer en caso de que el usuario o el sistema no pueda llegar al fondo completo de la lista por ningún motivo.

También vale la pena destacar que el oyente de cambio de desplazamiento se llamará a veces con valores negativos o valores mayores que la altura de la vista. Presumiblemente, estos valores representan el "momento" de la acción de desplazamiento. Sin embargo, a menos que se maneje adecuadamente (piso / abs), pueden causar problemas al detectar la dirección de desplazamiento cuando la vista se desplaza hacia arriba o hacia abajo del rango.

https://developer.android.com/reference/android/view/View.html#setOnScrollChangeListener(android.view.View.OnScrollChangeListener)

Siempre debemos añadir scrollView.getPaddingBottom() para que coincida con la altura de desplazamiento completo porque alguna vista de desplazamiento tiene un relleno en el archivo xml para que el caso no vaya a funcionar.

 scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { if (scrollView != null) { View view = scrollView.getChildAt(scrollView.getChildCount()-1); int diff = (view.getBottom()+scrollView.getPaddingBottom()-(scrollView.getHeight()+scrollView.getScrollY())); // if diff is zero, then the bottom has been reached if (diff == 0) { // do stuff } } } }); 

Para determinar si está al final de su ScrollView personalizado también podría usar una variable miembro y almacenar la última posición y. A continuación, puede comparar la última posición y con la posición de desplazamiento actual.

 private int scrollViewPos; ... @Override public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) { //reached end of scrollview if (y > 0 && scrollViewPos == y){ //do something } scrollViewPos = y; } 
  • Android RelativeLayout cambiar altura de forma programática
  • Android: ¿cuál es mejor, viewpager, galería, vista de desplazamiento horizontal ... o?
  • Scrollview se extiende más allá de la parte inferior de la pantalla
  • OnScrollChanged encender varias veces para desplazarse final en scrollView
  • ¿La lógica detrás de startScroll en scroller?
  • OverScrollBy no siempre se recupera en la plataforma Lollipop (5.x)
  • Detectar el fin del fling en ScrollView
  • ¿Podría mantener la posición de ScrollView después de volver a Fragment anterior como ListView?
  • Recyclerview dentro de ScrollView no se desplaza suavemente
  • ¿Cómo agregar una vista de desplazamiento a toda una actividad?
  • Desplácese la página cuando el teclado suaves aparece
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.