La solución es bastante simple, pero duele. Tuve que implementar exactamente esto dentro de un programa que hice recientemente.Sin embargo, hay algunas cosas trucos por las que tienes que moverte. Cabe señalar que las diferentes versiones del sistema operativo tienen diferentes experiencias. Se requiere cierta experiencia o un toque para hacer que esto funcione, ya que el dibujo a veces se ve negativamente afectado por este método. Mientras que I tengo una copia de trabajo, el código que proporciono no es para todos, y está sujeto a cualquier otro cambio o personalización que se haya realizado en su código.
- conjunto
android:layout_width
a wrap_content
- conjunto
android:layout_height
a wrap_content
- En su código:
- determinar el número de filas que tendrá.
- divida el número de elementos por el número de filas.
- agregar gridView.
setStretchMode(NO_STRETCH);
- agregar gridView.
setNumColumns(
número de columnas );
- agregar gridView.
setColumnWidth(
una anchura en píxeles explícita );
- para desplazarse:
- Usted puede simplemente utilizar GridView.
scrollBy()
en su onTouchEvent()
Estos son los pasos. Todos son necesarios para que funcione. La clave es NO_STRETCH con un número explícito de columnas con un ancho específico. Se pueden proporcionar más detalles, si necesita una aclaración. Incluso puede usar un VelocityTracker o onFling para manejar el arrojamiento. Tengo snappingToPage habilitado en el mío. Con esta solución, ni siquiera es necesario anular onDraw()
o onLayout()
. Esas tres líneas de código eliminan la necesidad de una WebView o cualquier otra incrustación o anidación.
El desplazamiento bidireccional también es bastante fácil de implementar. Aquí hay una solución de código simple:
Primero, en su clase, comience a rastrear las posiciones X e Y haciendo dos miembros de la clase. También agregue el seguimiento del estado;
// Holds the last position of the touch event (including movement)
int myLastX;
int myLastY;
// Tracks the state of the Touch handling
final static private int TOUCH_STATE_REST = 0;
final static private int TOUCH_STATE_SCROLLING = 1;
int myState = TOUCH_STATE_REST;
En segundo lugar, asegúrese de comprobar si hay movimiento en sentido vertical, de esa manera usted todavía puede hacer clic o longclick las propias imágenes.
@Override public boolean onInterceptTouchEvent(final MotionEvent ev)
{//User is already scrolling something. If we haven't interrupted this already,
// then something else is handling its own scrolling and we should let this be.
// Once we return TRUE, this event no longer fires and instead all goes to
// onTouch() until the next TouchEvent begins (often beginning with ACTION_DOWN).
if ((ev.getAction() == MotionEvent.ACTION_MOVE)
&& (myState != TOUCH_STATE_REST))
return false;
// Grab the X and Y positions of the MotionEvent
final float _x = ev.getX();
final float _y = ev.getY();
switch (ev.getAction())
{ case MotionEvent.ACTION_MOVE:
final int _diffX = (int) Math.abs(_x - myLastX);
final int _diffY = (int) Math.abs(_y - myLastY);
final boolean xMoved = _diffX > 0;
final boolean yMoved = _diffY > 0;
if (xMoved || yMoved)
myState = TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_DOWN:
// Remember location of down touch
myLastX = _x;
myLastY = _y;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (myState == TOUCH_STATE_SCROLLING)
// Release the drag
myState = TOUCH_STATE_REST;
}
//If we are not At Rest, start handling in our own onTouch()
return myState != TOUCH_STATE_REST;
}
Después de que el GridView sabe que se está desplazando, enviará todos los eventos de toque a onTouch. Haga su desplazamiento aquí.
@Override public boolean onTouchEvent(final MotionEvent ev)
{
final int action = ev.getAction();
final float x = ev.getX();
final float y = ev.getY();
final View child;
switch (action)
{
case MotionEvent.ACTION_DOWN:
//Supplemental code, if needed
break;
case MotionEvent.ACTION_MOVE:
// This handles Scrolling only.
if (myState == TOUCH_STATE_SCROLLING)
{
// Scroll to follow the motion event
// This will update the vars as long as your finger is down.
final int deltaX = (int) (myLastX - x);
final int deltaY = (int) (myLastY - y);
myLastX = x;
myLastY = y;
scrollBy(deltaX, deltaY);
}
break;
case MotionEvent.ACTION_UP:
// If Scrolling, stop the scroll so we can scroll later.
if (myState == TOUCH_STATE_SCROLLING)
myState = TOUCH_STATE_REST;
break
case MotionEvent.ACTION_CANCEL:
// This is just a failsafe. I don't even know how to cancel a touch event
myState = TOUCH_STATE_REST;
}
return true;
}
Si supuesto, esta solución se mueve a X e Y al mismo tiempo. Si desea mover solo una dirección a la vez, puede diferenciar fácilmente al verificar la mayor de las diferencias X e Y. (es decir, Math.abs(deltaX) > Math.abs(deltaY)
) A continuación se muestra una muestra parcial para un desplazamiento direccional, pero puede cambiar entre las direcciones X o Y.
3b.Cambiar esto en su OnTouch()
si desea manejar una dirección a la vez:
case MotionEvent.ACTION_MOVE:
if (myState == TOUCH_STATE_SCROLLING)
{
//This will update the vars as long as your finger is down.
final int deltaX = (int) (myLastX - x);
final int deltaY = (int) (myLastY - y);
myLastX = x;
myLastY = y;
// Check which direction is the bigger of the two
if (Math.abs(deltaX) > Math.abs(deltaY))
scrollBy(deltaX, 0);
else if (Math.abs(deltaY) > Math.abs(deltaX))
scrollBy(0, deltaY);
// We do nothing if they are equal.
}
break;
FuzzicalLogic
Me habría proporcionado una muestra completa, pero esas son las únicas 3 líneas que son importantes y pueden ser colocados en cualquier lugar. Tengo tres de tales GridViews y cada uno los coloca en un lugar diferente (uno en la declaración inicial, uno en un CursorAdapter, y uno en un método diferente que se llama desde varios lugares. –
Y ... como nota al margen, esto tomó Me dio una semana de preguntas y preguntas. Estaba tan feliz cuando lo hice. –
¿A qué se refiere mScroller en este contexto? Si elaboras un poco te otorgaré la recompensa. –