Detección de gestos de lanzamiento en diseño de cuadrícula
Quiero que fling
la detección de gestos funcione en mi aplicación de Android.
Lo que tengo es uno GridLayout
que contiene 9 ImageView
s. La fuente se puede encontrar aquí: Diseño de cuadrícula de Romain Guys .
Ese archivo que tomé es de la aplicación Photostream de Romain Guy y solo ha sido ligeramente adaptado.
Para la situación de un simple clic, solo necesito configurar onClickListener
para cada uno ImageView
que agrego que sea el principal activity
que implementa View.OnClickListener
. Parece infinitamente más complicado implementar algo que reconozca un archivo fling
. ¿Supongo que esto se debe a que puede extenderse views
?
Si mi actividad se implementa,
OnGestureListener
no sé cómo configurarla como detector de gestos para lasGrid
vistasImage
que agrego.public class SelectFilterActivity extends Activity implements View.OnClickListener, OnGestureListener { ...
Si mi actividad se implementa,
OnTouchListener
entonces no tengo ningúnonFling
método para hacerlooverride
(tiene dos eventos como parámetros que me permiten determinar si la aventura fue digna de mención).public class SelectFilterActivity extends Activity implements View.OnClickListener, OnTouchListener { ...
Si hago una costumbre
View
, comoGestureImageView
esa se extiende,ImageView
no sé cómo saber la actividad quefling
ha ocurrido desde la vista. En cualquier caso, probé esto y no se llamaron los métodos cuando toqué la pantalla.
Realmente solo necesito un ejemplo concreto de cómo funciona esto en todas las vistas. ¿Qué, cuándo y cómo debo adjuntar esto listener
? También necesito poder detectar clics únicos.
// Gesture detection
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int dx = (int) (e2.getX() - e1.getX());
// don't accept the fling if it's too short
// as it may conflict with a button push
if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.absvelocityY)) {
if (velocityX > 0) {
moveRight();
} else {
moveLeft();
}
return true;
} else {
return false;
}
}
});
¿Es posible colocar una vista transparente en la parte superior de mi pantalla para capturar aventuras?
Si elijo no mostrar inflate
mis vistas de imágenes secundarias desde XML, ¿puedo pasarlas GestureDetector
como parámetro de constructor a una nueva subclase que ImageView
creo?
Esta es la actividad muy simple para la que estoy intentando que fling
funcione la detección: SelectFilterActivity (adaptado de photostream) .
He estado mirando estas fuentes:
Detectar gestos - Tutorial
Documentos SDK
Código de calculadora
Nada me ha funcionado hasta ahora y esperaba algunos consejos.
Gracias a Code Shogun , cuyo código adapté a mi situación.
Deje que su actividad se implemente OnClickListener
como de costumbre:
public class SelectFilterActivity extends Activity implements OnClickListener {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* ... */
// Gesture detection
gestureDetector = new GestureDetector(this, new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// nothing
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
}
}
Adjunte su detector de gestos a todas las vistas que agregue al diseño principal;
// Do this for each view added to the grid
imageView.setOnClickListener(SelectFilterActivity.this);
imageView.setOnTouchListener(gestureListener);
Observe con asombro cómo se ven afectados sus métodos anulados, tanto los onClick(View v)
de la actividad como los onFling
del gesto oyente.
public void onClick(View v) {
Filter f = (Filter) v.getTag();
FilterFullscreenActivity.show(this, input, f);
}
El baile posterior a la aventura es opcional pero recomendable.
Una de las respuestas anteriores menciona el manejo de diferentes densidades de píxeles, pero sugiere calcular los parámetros de deslizamiento manualmente. Vale la pena señalar que en realidad puedes obtener valores escalados y razonables del sistema usando ViewConfiguration
la clase:
final ViewConfiguration vc = ViewConfiguration.get(getContext());
final int swipeMinDistance = vc.getScaledPagingTouchSlop();
final int swipeThresholdVelocity = vc.getScaledMinimumFlingVelocity();
final int swipeMaxOffPath = vc.getScaledTouchSlop();
// (there is also vc.getScaledMaximumFlingVelocity() one could check against)
Noté que el uso de estos valores hace que la "sensación" de lanzar sea más consistente entre la aplicación y el resto del sistema.