Cómo y comprensión del evento de arrastre y zoom con GLSurfaceView
Tenía todo trabajando con esta aplicación de prueba he hecho que muestra un objeto 3D utilizando el estándar de vértice, color y punto de amortiguación.
Puedo..
- LibGDX - Obtener deslizar hacia arriba o deslizar derecha, etc?
- ¿Cómo puede un servicio escuchar los gestos / eventos táctiles?
- Android - overdraw diseño permite toque a través de LinearLayout
- Cómo interceptar eventos de contacto desde ViewPager.OnPageChangeListener
- Toca y arrastra la imagen en android
- Gire el objeto con eventos táctiles
- Render object con openGL ES 1.0 usando GL10
- Todo funciona muy bien
Ahora quiero ser capaz de acercar y alejar usando dos dedos para un movimiento de "pellizco". He encontrado algunos buenos tutoriales y código de ejemplo, pero es sobre todo para ImageViews. Todavía soy semi-nuevo para Android y no entiendo completamente cómo hacer que este trabajo de función de zoom para GLSurfaceView.
A continuación se muestra el código que tengo hasta ahora para la clase de actividad. El primer manipulador táctil es para el evento de zoom que encontré a través de un tutorial diseñado para ImageView (usé esto porque pensé que sería una conversión fácil). El segundo controlador es para el evento de rotación, que funciona muy bien.
Gracias de antemano y espero que este post ayudará a otros con el mismo problema. Estaré parado para cualquier edición o adiciones necesarias.
// Activity for rendering 3D object openGL ES 1.0 public class GL_ExampleActivity extends Activity { private GLSurfaceView surface; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); surface = new GL_ExampleSurfaceView(this); setContentView(surface); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); surface.onPause(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); surface.onResume(); } } class GL_ExampleSurfaceView extends GLSurfaceView { private static final String TAG = "Touch"; Matrix matrix_new = new Matrix(); Matrix last_matrix = new Matrix(); static final int NONE = 0; static final int DRAG = 1; static final int ZOOM = 2; int mode = NONE; PointF start = new PointF(); PointF mid = new PointF(); float oldDist = 1f; private final float SCALE_FACTOR = 180.0f / 320; private GLRenderer renderer; private float previous_x; private float previous_y; public GL_ExampleSurfaceView(Context context) { super(context); renderer = new GLRenderer(); setRenderer(renderer); setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); } @Override public boolean onTouchEvent(MotionEvent e) { // handler for drag and zoom events switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: last_matrix.set(matrix_new); start.set(e.getX(), e.getY()); Log.d(TAG, "mode=DRAG"); mode = DRAG; //requestRender(); break; case MotionEvent.ACTION_POINTER_DOWN: oldDist = finger_distance(e); Log.d(TAG, "oldDist=" + oldDist); if (oldDist > 10f) { last_matrix.set(matrix_new); finger_distance_midpoint(mid, e); mode = ZOOM; Log.d(TAG, "mode=ZOOM"); } //requestRender(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; Log.d(TAG, "mode=NONE"); //requestRender(); break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { matrix_new.set(last_matrix); matrix_new.postTranslate(e.getX() - start.x, e.getY() - start.y); } else if (mode == ZOOM) { float newDist = finger_distance(e); Log.d(TAG, "newDist=" + newDist); if (newDist > 10f) { matrix_new.set(last_matrix); float scale = newDist / oldDist; matrix_new.postScale(scale, scale, mid.x, mid.y); } } //requestRender(); break; } //view.setImageMatrix(matrix_new); // handler for rotation event, y and x axis float x = e.getX(); float y = e.getY(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: float dx = x - previous_x; float dy = y - previous_y; if (y > getHeight() / 2) { dx = dx * -1 ; } if (x < getWidth() / 2) { dy = dy * -1 ; } renderer.angle_x += dx * SCALE_FACTOR; renderer.angle_y += dy * SCALE_FACTOR; requestRender(); } previous_x = x; previous_y = y; return true; } private float finger_distance(MotionEvent e) { float x = e.getX(0) - e.getX(1); float y = e.getY(0) - e.getY(1); return FloatMath.sqrt(x * x + y * y); } private void finger_distance_midpoint(PointF point, MotionEvent e) { float x = e.getX(0) + e.getX(1); float y = e.getY(0) + e.getY(1); point.set(x / 2, y / 2); } }
Gracias de nuevo…
- Diferencia entre onSingleTapConfirmed y onSingleTapUp
- Obtener eventos táctiles (coordenadas, MotionEvents, etc.) en un servicio
- ¿Detectar la prensa del tacto contra la prensa larga contra el movimiento?
- La animación de la vista no cambia el área táctil
- (Disposición de Android) Solución para colocar el botón en la parte superior de la imagen de forma irregular o obtener la detección de toque (zona de contacto) de área particular de la imagen?
- Android - ¿Cómo hacer que un icono brille en el tacto?
- Animación de RecyclerView en el clic de artículo
- Slow eventos de toque de Javascript en Android
Hay dos maneras obvias de abordar esto. Si sólo desea aumentar el tamaño de un objeto individual, puede utilizar glScalef al dibujar el objeto. El uso de scalef es fácil y relativamente sencillo, pero no es exactamente lo que estás pidiendo.
Otra solución es aplicar un factor de escala a su matriz de proyección que producirá el efecto deseado. Para lograr esto, solo multiplique las distancias izquierda, derecha, superior y inferior de su matriz de proyección por una escala similar a la anterior.
Gl.glFrustumf (ancho / 2 * zoom, ancho / 2 * zoom, altura / 2 * zoom, altura / 2 * zoom, 1, -1);
(Tenga en cuenta, si está utilizando una matriz ortogonal que estará utilizando glOrthof en su lugar)
Si está interesado, puede encontrar más información sobre la matriz de proyección aquí
- Cómo probar una aplicación de Android en un AVD con un nivel de API inferior al de Eclipse
- Subir varios archivos de Android a AppEngine en 1 solicitud