SDK de Android: no escala en el centro del tacto
Tengo un pequeño problema con mi aplicación. Acabo de implementar pinch zoom, pero cuando pellizco para hacer zoom, la imagen no escala en el centro de los 2 puntos como se muestra en las imágenes de abajo. Imagen 1 es donde mis dedos son antes de pellizcar y la imagen 2 es mostrar que no ha escalado en el centro de mis dedos como debería.
Imagen 1 vs Imagen 2:
- Descargar Android SDK de forma programática
- ¿Existe una biblioteca de código abierto de OCR o sdk (gratuita) para Android e iOS?
- Cuando isValidFragment () de android de PreferenceActivity se llama?
- Android Studio: "La instalación del SDK no tiene" Extras> Android Support Repository "instalado", PERO HA SIDO INSTALADO
- Problema de instalación de Android SDK
Aquí está mi código:
package com.jpiionefourone.guitarimage; import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; public class MultiTouchView extends View { private Drawable mIcon; private float mPosX; private float mPosY; private float mLastTouchX; private float mLastTouchY; private static final int INVALID_POINTER_ID = -1; // The 'active pointer' is the one currently moving our object. private int mActivePointerId = INVALID_POINTER_ID; private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; public MultiTouchView(Context context) { this(context, null, 0); } public MultiTouchView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MultiTouchView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mIcon = context.getResources().getDrawable(R.drawable.guitar); mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight()); // Create our ScaleGestureDetector mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); } @Override public boolean onTouchEvent(MotionEvent ev) { // Let the ScaleGestureDetector inspect all events. mScaleDetector.onTouchEvent(ev); final int action = ev.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { final float x = ev.getX(); final float y = ev.getY(); mLastTouchX = x; mLastTouchY = y; mActivePointerId = ev.getPointerId(0); break; } case MotionEvent.ACTION_MOVE: { final int pointerIndex = ev.findPointerIndex(mActivePointerId); final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); // Only move if the ScaleGestureDetector isn't processing a gesture. if (!mScaleDetector.isInProgress()) { final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; invalidate(); } mLastTouchX = x; mLastTouchY = y; break; } case MotionEvent.ACTION_UP: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_CANCEL: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_POINTER_UP: { final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = ev.getPointerId(pointerIndex); if (pointerId == mActivePointerId) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mLastTouchX = ev.getX(newPointerIndex); mLastTouchY = ev.getY(newPointerIndex); mActivePointerId = ev.getPointerId(newPointerIndex); } break; } } return true; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.translate(mPosX, mPosY); canvas.scale(mScaleFactor, mScaleFactor); mIcon.draw(canvas); canvas.restore(); } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); // Don't let the object get too small or too large. mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); invalidate(); return true; } } }
Gracias,
Jared
- "No se puede encontrar la base de datos de API; Comprobación de API no se realizó "en SDK de aplicaciones de Android con Eclipse
- Tumblr SDK (o Sharekit) para Android, ¿existe?
- Android SDK obtiene un error NotRegistered de GCM después de unas horas
- Android Studio AVD, CRASH, GRADLE PROBLEMAS, no se puede iniciar
- Android SDk Manager - Descargar SDK 3.0 a 3.2
- Modifique AIRPLANE_MODE_ON en Android 4.2 (y superior)
- Administrador de SDK de Android El par de SSL se ha cerrado incorrectamente
- Mejor NFC SDK para ACR122U y ACR1222L
En su clase ScaleListener
sólo ajusta mScaleFactor
así que, de hecho, la imagen de hecho no zoom alrededor del centro de su gesto multi-touch!
Además, es necesario actualizar mPosX
y mPosY
para utilizar un centro diferente de escalado.
Para una de mis propias aplicaciones, he usado algo como esto:
final float scale = detector.getScaleFactor(); mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor * scale, 5.0f)); if (mScaleFactor < 5f) { // 1 Grabbing final float centerX = detector.getFocusX(); final float centerY = detector.getFocusY(); // 2 Calculating difference float diffX = centerX - mPosX; float diffY = centerY - mPosY; // 3 Scaling difference diffX = diffX * scale - diffX; diffY = diffY * scale - diffY; // 4 Updating image origin mPosX -= diffX; mPosY -= diffY; }
Básicamente, calcula el cambio relativo del origen de la imagen por
- Agarrando el origen de su gesto multi-touch (
getFocus()
) - Calculando la diferencia entre el origen de la imagen (
diffX
ydiffY
) - Aplicando el factor de escala
- Y actualizar el origen de la imagen utilizando la diferencia escalada
Esto (todavía) funciona para mi situación. No sé si ambos usamos (d) los mismos sistemas de coordenadas, pero algo como esto le ayudará a escalar adecuadamente la imagen en el centro del gesto multitáctil.
Me tomó realmente mucho tiempo para conseguir este trabajo .. sin embargo gracias por casi código de trabajo! No estoy seguro de que estaba simplemente jugando o lo que pero con estos cambios en el código Tengo mi trabajo de zoom como yo quería! Espero que esto sea seguro tiempo someones.
mScaleFactor *= detector.getScaleFactor(); mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 3.0f)); scale = mScaleFactor / scaleAtm mTranslateMatrix.preTranslate(diffX, diffY); mTranslateMatrix.invert(mTranslateMatrixInverse); mPosX += diffX; mPosY += diffY; scaleAtm = mScaleFactor;
Al principio scaleAtm = 1.
- Cambiar el tamaño de los diseños de forma dinámica con ViewFlipper
- Límite de métodos 64K por un archivo dex en Android