2011-04-21 21 views
8

Mi aplicación contiene un área llena de botones. Deseo implementar la actividad de tal manera, que el gesto arrojado sobre el área del botón lo cambiaría a una de las otras dos áreas (usando ViewFlipper).Android, gestos sobre widgets clicables

He hecho dos enfoques para detectar gestos. El primero involucró el uso de GestureDetector. Sin embargo, los eventos de movimiento táctil sobre el botón no elevaron el método de actividad onTouchEvent, por lo que, en consecuencia, no pude haberlo reenviado a la clase GestureDetector. Una falla, en resumen.

El segundo enfoque - involucró el uso de GestureOverlayView. Esta vez, sin embargo, he llegado al segundo extremo: no solo se detectó el gesto, sino que también se informó un clic sobre el botón sobre el cual se realiza el gesto.

Deseo que la interfaz funcione de la siguiente manera: si el usuario toca el botón y suelta el botón táctil (o mueve el dedo solo un poco), el botón informa de que se hace clic y no se detecta ningún gesto. Por otro lado, si el usuario toca la pantalla y hace un movimiento más largo, se detectará el gesto y no se informará ningún evento de clic por el botón.

Implementé una pequeña aplicación de prueba de concepto. El código de actividad XML sigue: código de Java

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"> 
    <android.gesture.GestureOverlayView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/overlay"> 
    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> 
    <TextView android:id="@+id/display" android:layout_width="match_parent" android:layout_height="wrap_content" /> 
    <Button android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/button"/> 
    </LinearLayout> 
    </android.gesture.GestureOverlayView> 
</LinearLayout> 

La actividad sigue:

package spk.sketchbook; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.TextView; 
import android.widget.Toast; 
import android.gesture.*; 
import android.gesture.GestureOverlayView.OnGestureListener; 

public class Main extends Activity implements OnGestureListener, OnClickListener 
{  
    private void SetupEvents() 
    { 
    GestureOverlayView ov = (GestureOverlayView)findViewById(R.id.overlay); 
    ov.addOnGestureListener(this); 

    Button b = (Button)findViewById(R.id.button); 
    b.setOnClickListener(this); 
    } 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 

    SetupEvents(); 
    } 

    @Override 
    public void onGesture(GestureOverlayView arg0, MotionEvent arg1) 
    { 
    TextView tv = (TextView)findViewById(R.id.display); 
    tv.setText("Gesture"); 
    } 

    @Override 
    public void onGestureCancelled(GestureOverlayView arg0, MotionEvent arg1) 
    { 

    } 

    @Override 
    public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) 
    { 

    } 

    @Override 
    public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) 
    { 

    } 

    @Override 
    public void onClick(View v) 
    { 
    TextView tv = (TextView)findViewById(R.id.display); 
    tv.setText("Click"); 
    } 


} 

La pregunta es: ¿cómo poner en práctica este tipo de interfaz, que puede decidir, si la acción del usuario se tratará como el gesto o haga clic en el botón?

Recuerdos - Spook.

+0

http://stackoverflow.com/questions/937313/android-basic-gesture-detection Puede ayudar si alguien no responde directamente – CityView

Respuesta

3

Resuelto yo mismo. La idea es capturar eventos de gestos de GestureOverlayView y, además de pasarlos a GestureDetector, medir la distancia del gesto del usuario. La distancia se almacenará en el campo de una actividad privada (por lo tanto, estará disponible para todos los manejadores de eventos). Finalmente, los manejadores de arrojar y hacer clic deben verificar el valor de este campo; si está por debajo de cierto valor (digamos, 10 píxeles estarán bien), debe interpretarse como un clic. De lo contrario, como un gesto.

Tenga en cuenta que el botón se verá cliqueado y se llamará a su controlador de clic. Decidí crear un controlador de clics de bajo nivel (asociado a todos los botones sobre GestureOverlayView), que hace la comprobación de gesto/clic y si el resultado es un clic, elige uno de los manejadores de clics de nivel superior.

La solución funciona para mí; sin embargo, si uno desea desactivar el aspecto del botón y evitar que se llame al controlador, probablemente implicaría redefinir el botón y/o los componentes de GestureOverlayView.

2

otra solución: Hacer esta función:

public void SetSwipe(View v, final GestureDetector gestureScanner){ 
    // Sets scroll view listener 
    v.setOnTouchListener(new OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
       if (gestureScanner.onTouchEvent(event)) 
       return true; 
       else 
       return false; 
     } 
    }); 
} 

y lo llaman para cada Widget de la siguiente manera:

scfSetTag.SetSwipe(svAllView, gestureScanner); 

Si necesita hacer esto desde muchas actividades o fragmentos, se puede hacer una class.java file y crear una instancia de esta clase en cada actividad que necesita implementar el deslizamiento. Esto detecta tanto deslizar como hacer clic en cualquier botón. Espero ayuda!

Cuestiones relacionadas