android user-interface drag-and-drop scrollview

android - Anulando onTouchEvent compitiendo con ScrollView



user-interface drag-and-drop (3)

Hay un evento de Android llamado MotionEvent.ACTION_CANCEL (value = 3). Todo lo que hago es anular el método onTouchEvent de mi control personalizado y capturar este valor. Si detecto esta condición entonces respondo en consecuencia.

Aquí hay un código:

@Override public boolean onTouchEvent(MotionEvent event) { if(isTouchable) { int maskedAction = event.getActionMasked(); if (maskedAction == MotionEvent.ACTION_DOWN) { this.setTextColor(resources.getColor(R.color.octane_orange)); initialClick = event.getX(); } else if (maskedAction == MotionEvent.ACTION_UP) { this.setTextColor(defaultTextColor); endingClick = event.getX(); checkIfSwipeOrClick(initialClick, endingClick, range); } else if(maskedAction == MotionEvent.ACTION_CANCEL) this.setTextColor(defaultTextColor); } return true; }

Desde una descripción simplista, tengo una vista personalizada que contiene algunos mapas de bits que el usuario puede arrastrar y cambiar de tamaño.

La forma en que lo hago es bastante estándar, ya que anulo onTouchEvent en mi CustomView y verifico si el usuario está tocando dentro de una imagen, etc.

Mi problema surge cuando quiero colocar este CustomView en un ScrollView. Esto funciona, pero ScrollView y CustomView parecen competir por MotionEvents, es decir, cuando intento arrastrar una imagen, se mueve lentamente o la vista se desplaza.

Pienso que es posible que tenga que extender un ScrollView para poder anular onInterceptTouchEvent y hacerle saber si el usuario está dentro de los límites de una imagen para no intentar desplazarse. Pero luego, debido a que ScrollView está en una posición más alta en la jerarquía, ¿cómo obtendría acceso al estado actual de CustomView?

¿Hay alguna manera mejor?


Ninguna de las soluciones encontradas funcionó "fuera de la caja" para mí, probablemente porque mi vista personalizada amplía la vista , no ViewGroup , y por lo tanto no puedo implementar onInterceptTouchEvent .

También llamar a getParent().requestDisallowInterceptTouchEvent(true) fue lanzar NPE, o no hacer nada en absoluto.

Finalmente así es como resolví el problema:
Dentro de su onTouchEvent personalizada onTouchEvent requestDisallow... cuando su vista se ocupará del evento. Por ejemplo:

@Override public boolean onTouchEvent(MotionEvent event) { Point pt = new Point( (int)event.getX(), (int)event.getY() ); if (event.getAction() == MotionEvent.ACTION_DOWN) { if (/*this is an interesting event my View will handle*/) { // here is the fix! now without NPE if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } clicked_on_image = true; } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { if (clicked_on_image) { //do stuff, drag the image or whatever } } else if (event.getAction() == MotionEvent.ACTION_UP) { clicked_on_image = false; } return true; }

Ahora mi vista personalizada funciona bien, manejando algunos eventos y dejando que scrollView capture los que no nos interesan. Encontró la solución aquí: http://android-devblog.blogspot.com.es/2011/01/scrolling-inside-scrollview.html

Espero eso ayude.


Normalmente, Android usa una pulsación larga para comenzar a arrastrar en casos como este, ya que ayuda a desconcertar cuando el usuario intenta arrastrar un elemento en lugar de desplazarse por el contenedor del elemento. Pero si tiene una señal inequívoca cuando el usuario comienza a arrastrar un elemento, pruebe getParent().requestDisallowInterceptTouchEvent(true) desde la vista personalizada cuando sepa que el usuario está comenzando a arrastrar. (Docs para este método here .) Esto evitará que ScrollView intercepte eventos táctiles hasta el final del gesto actual.