Vista ScrollView con niños, cómo interceptar desplazamiento condicional

Tengo un contenedor ViewGroup , permite llamar a la pantalla dentro de un ScrollView . Esta vista de contenedor aloja una serie de otras Views , llamémoslas widgets , y algunas de ellas están interesadas en evitar que ScrollView se desplace y utilice sus propios MotionEvent (por ejemplo, una imagen en forma de paneles)

No puedo averiguar la estrategia de intercepción de eventos apropiados para usar. ScrollView siempre procesa el evento antes de que los niños o los niños procesen el evento, pero scrollview está deshabilitado.

He leído sobre emitir getParent().requestDisableInterceptTouchEvent() en las vistas secundarias si esta vista quiere capturar el evento, pero su onTouchEvent no se llama, supongo que ScrollView ha engullido el evento de antemano. Supongo que el hecho de que tengo 2 niveles de capas (contenedor + widgets) impide que esto funcione, supongo que el contenedor ViewGroup tiene que desempeñar un papel importante aquí, pero no puedo averiguar cuál …

¿Puedo saber, en el nivel onInterceptTouchEvent ScrollView's , qué widget en el viewGroup del contenedor se ha tocado para decidir si debo interceptar o no?

o…

¿Cómo pueden las capas 'widget' en ViewGroup obtener el evento antes de ScrollView para que pueda llamar a getParent().onRequestDisableInterceptTouch() … o es getParent().getParent().onRequestDisableInterceptTouch() ?

Gracias por adelantado

He leído preguntas relacionadas, pero no hay suerte … Manejo de eventos táctiles en ScrollView Android

Bueno, después de una noche de coca cola y depuración me las arreglé para conseguir que esto funcione. Comparto la solución sólo en caso de que sea de interés para cualquier persona, porque me tomó bastante tiempo para que funcione.

No conseguí ponerlo en funcionamiento con getParent().onRequestDisableInterceptTouch() , estaba cerca, pero no pude encontrar una forma para que los widgets secundarios obtengan los MotionEvents que necesitan para desplazarse una vez que intercepté el toque en el padre, Así que aunque el rollo externo se evitó correctamente, los widgets internos no se desplazaron.

Así que la solución es interceptTouchEvents en los niños SOLAMENTE , y si los niños es desplazable (propiedad conocida), y el toque es ACTION_DOWN, deshabilite la vista de desplazamiento dos niveles arriba. Si el toque es ACTION_UP, activamos la vista de desplazamiento.

Para habilitar / deshabilitar el scrollview sólo intercepto el evento táctil y con un filtro de bandera el evento o no.

Hice tres clases auxiliares, una para el ScrollView, otra para el contenedor, una para los widgets:

Esta clase envuelve todos los widgets y, si llamo a setNeedsScroll (true), los toques serán interceptados, y cuando se toca, le indicará al scrollview que se desactive. Cuando se suelta el tacto, volverá a habilitar la vista de desplazamiento.

 class WidgetWrapperLayout extends FrameLayout { private boolean mNeedsScroll=false; public WidgetWrapperLayout(Context context) { super(context); } /** Called anytime, ie, during construction, to indicate that this * widget uses vertical scroll, so we need to disable its container scroll */ public void setNeedsScroll(boolean needsScroll) { mNeedsScroll=needsScroll; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mNeedsScroll) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: ((SlideLayout)getParent()).setEnableScroll(false); break; case MotionEvent.ACTION_UP: ((SlideLayout)getParent()).setEnableScroll(true); break; } return false; } return super.onInterceptTouchEvent(ev); } } 

Este es el contenedor, único hijo de la vista de scrollview , y tiene los diferentes widgets. Sólo proporciona métodos para los niños para que puedan activar / desactivar el desplazamiento:

 public class ContainerLayout extends FrameLayout { public ContainerLayout(Context context) { super(context); } public void setEnableScroll(boolean status) { if (Conf.LOG_ON) Log.d(TAG, "Request enable scroll: "+status); ((StoppableScrollView)getParent()).setScrollEnabled(status); } } 

Y finalmente un scrollview capaz de desactivación. Desactiva el scroll 'old-skool', interceptar y bloquear eventos.

 public class StoppableScrollView extends ScrollView { private String TAG="StoppableScrollView"; private boolean mDisableScrolling=false; public StoppableScrollView(Context context) { super(context); } /** Enables or disables ScrollView scroll */ public void setScrollEnabled (boolean status) { if (Conf.LOG_ON) Log.d(TAG, "Scroll Enabled "+status); mDisableScrolling=!status; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mDisableScrolling) return false; return super.onInterceptTouchEvent(ev); } } 

Implemente View.OnTouchListener en su actividad y añada ese oyente a ScrollView. A continuación, devuelve true en onTouchEvent(...) . Antes de regresar llame al onTouch de los niños que desea manejar ese evento.

  • Utilice una barra de acción contextual personalizada para la selección de texto de WebView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.