traseras tomar para p10 mejor gran frontal fotos cual con celulares celular camaras camara android imageview zoom pinch pan

tomar - Zoom y Panorámica ImageView Android



mejor camara de celular 2017 (4)

Parece que el canvas.scale () en la declaración ''else'' del método ''onDraw'' requería mLastGestureX y mLastGestureY para detener el salto. También actualizo mLastTouchX y mLastTouchY cuando vuelvo al análisis de un solo dedo en el ''caso MotionEvent.ACTION_POINTER_UP''

Aquí está la final, puede no adaptarse a todos porque no restringe el panorama de los límites de las imágenes pasadas, pero eso debería ser fácil de lograr, hay muchas discusiones sobre ese tema.

import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.widget.ImageView; public class MyImageView extends ImageView { private static final int INVALID_POINTER_ID = -1; private float mPosX; private float mPosY; private float mLastTouchX; private float mLastTouchY; private float mLastGestureX; private float mLastGestureY; private int mActivePointerId = INVALID_POINTER_ID; private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; public MyImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } public MyImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); 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: { if (!mScaleDetector.isInProgress()) { final float x = ev.getX(); final float y = ev.getY(); mLastTouchX = x; mLastTouchY = y; mActivePointerId = ev.getPointerId(0); } break; } case MotionEvent.ACTION_POINTER_1_DOWN: { if (mScaleDetector.isInProgress()) { final float gx = mScaleDetector.getFocusX(); final float gy = mScaleDetector.getFocusY(); mLastGestureX = gx; mLastGestureY = gy; } break; } case MotionEvent.ACTION_MOVE: { // Only move if the ScaleGestureDetector isn''t processing a gesture. if (!mScaleDetector.isInProgress()) { final int pointerIndex = ev.findPointerIndex(mActivePointerId); final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; invalidate(); mLastTouchX = x; mLastTouchY = y; } else{ final float gx = mScaleDetector.getFocusX(); final float gy = mScaleDetector.getFocusY(); final float gdx = gx - mLastGestureX; final float gdy = gy - mLastGestureY; mPosX += gdx; mPosY += gdy; invalidate(); mLastGestureX = gx; mLastGestureY = gy; } 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); } else{ final int tempPointerIndex = ev.findPointerIndex(mActivePointerId); mLastTouchX = ev.getX(tempPointerIndex); mLastTouchY = ev.getY(tempPointerIndex); } break; } } return true; } @Override public void onDraw(Canvas canvas) { canvas.save(); canvas.translate(mPosX, mPosY); if (mScaleDetector.isInProgress()) { canvas.scale(mScaleFactor, mScaleFactor, mScaleDetector.getFocusX(), mScaleDetector.getFocusY()); } else{ canvas.scale(mScaleFactor, mScaleFactor, mLastGestureX, mLastGestureY); } super.onDraw(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, 10.0f)); invalidate(); return true; } } }

Creé una clase de zoom y pan para un ImageView.

Funciones que intento crear - Se desplaza con solo tocar y mover un dedo - Se acerca y se mueve con dos dedos y movimiento

En su mayor parte, esto funciona muy bien. Tiene un pequeño error cuando hago lo siguiente: - Me desplazo con un dedo (Estado: no hay problema) - Pongo un segundo dedo, hago un zoom y giro (Estado: no hay problema) - Suelte mi segundo dedo (Estado: La imagen salta un poco)

Estaba esperando que alguien me pudiera ayudar a resolver esto.

Estoy pensando que tiene que ver con restablecer mLastTouchX y mLastTouchY en "caso MotionEvent.ACTION_POINTER_UP"

¡Cualquier ayuda sería muy apreciada!

import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.widget.ImageView; public class MyImageView extends ImageView { private static final int INVALID_POINTER_ID = -1; private float mPosX; private float mPosY; private float mLastTouchX; private float mLastTouchY; private float mLastGestureX; private float mLastGestureY; private int mActivePointerId = INVALID_POINTER_ID; private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; public MyImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } public MyImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); 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: { if (!mScaleDetector.isInProgress()) { final float x = ev.getX(); final float y = ev.getY(); mLastTouchX = x; mLastTouchY = y; mActivePointerId = ev.getPointerId(0); } break; } case MotionEvent.ACTION_POINTER_1_DOWN: { if (mScaleDetector.isInProgress()) { final float gx = mScaleDetector.getFocusX(); final float gy = mScaleDetector.getFocusY(); mLastGestureX = gx; mLastGestureY = gy; } break; } case MotionEvent.ACTION_MOVE: { // Only move if the ScaleGestureDetector isn''t processing a gesture. if (!mScaleDetector.isInProgress()) { final int pointerIndex = ev.findPointerIndex(mActivePointerId); final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; invalidate(); mLastTouchX = x; mLastTouchY = y; } else{ final float gx = mScaleDetector.getFocusX(); final float gy = mScaleDetector.getFocusY(); final float gdx = gx - mLastGestureX; final float gdy = gy - mLastGestureY; mPosX += gdx; mPosY += gdy; invalidate(); mLastGestureX = gx; mLastGestureY = gy; } 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) { Log.d("DEBUG", "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) { canvas.save(); canvas.translate(mPosX, mPosY); if (mScaleDetector.isInProgress()) { canvas.scale(mScaleFactor, mScaleFactor, mScaleDetector.getFocusX(), mScaleDetector.getFocusY()); } else{ canvas.scale(mScaleFactor, mScaleFactor); } super.onDraw(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, 10.0f)); invalidate(); return true; } } }


He estado jugando con una solución a este problema durante más de una semana, y me está dando un montón de problemas. Sin embargo, reduje el problema significativamente. Su solución anterior NO funcionó para mí, pero mi solución a continuación está cerca. El problema es que salta cada vez que se presiona o se levanta un segundo dedo. Descubrí que esto sucede porque mPosX y mPosY no siempre son realmente lo que se supone que representan las variables. Esto es lo que quiero decir:

Cuando se llama a ACTION_MOVE y el código ingresa a la declaración "else" (para tratar los eventos de zoom), mPosX y mPosY solo cambian de acuerdo con el cambio de enfoque , no con el cambio en el zoom . Esto significa que funciona la panoramización con dos dedos, y el zoom con dos dedos funciona, pero mPosX y mPosY no cambian adecuadamente con respecto al cambio de zoom.

He estado tratando de encontrar formas de arreglar esto usando los cambios diferenciales en el zoom (mScaleDetector.getScaleFactor ()) y los cambios diferenciales en el enfoque, pero parece que no puedo trabajar lo suficiente en la lógica para encontrar algo que funcione .

Otra solución es mover todas las operaciones de zoom a OnTouchListener y deshacerse por completo de ScaleListener. Esto significa mucha más matemática, pero definitivamente sería una solución.

Aquí está onDraw:

@Override public void onDraw(Canvas c) { c.save(); if (mScaleDetector.isInProgress()) { c.scale(mScaleFactor, mScaleFactor, mLastGestureX - mPosX, mLastGestureY - mPosY); } else { c.scale(mScaleFactor, mScaleFactor, mLastGestureX, mLastGestureY); } c.translate(mPosX / mScaleFactor, mPosY / mScaleFactor); // drawing instruction here c.restore(); }

Aquí es cómo reacciona el código a las prensas de dedo:

@Override public boolean onTouchEvent(MotionEvent ev) { mScaleDetector.onTouchEvent(ev); final int action = ev.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { if (!mScaleDetector.isInProgress()) { final float x = ev.getX(); final float y = ev.getY(); mLastTouchX = x; mLastTouchY = y; mActivePointerId = ev.getPointerId(0); } break; } case MotionEvent.ACTION_POINTER_DOWN: { if (!mScaleDetector.isInProgress()) { final float gx = mScaleDetector.getFocusX(); final float gy = mScaleDetector.getFocusY(); mLastGestureX = gx; mLastGestureY = gy; } break; } case MotionEvent.ACTION_MOVE: { if (!mScaleDetector.isInProgress()) { Log.i("hi", "SD not in progress"); final int pointerIndex = ev.findPointerIndex(mActivePointerId); final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; invalidate(); mLastTouchX = x; mLastTouchY = y; } else { Log.i("hi", "SD in progress"); final float gx = mScaleDetector.getFocusX(); final float gy = mScaleDetector.getFocusY(); final float gdx = gx - mLastGestureX; final float gdy = gy - mLastGestureY; mPosX += gdx; mPosY += gdy; // SOMETHING NEEDS TO HAPPEN RIGHT HERE. invalidate(); mLastGestureX = gx; mLastGestureY = gy; } 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); } else { final int tempPointerIndex = ev.findPointerIndex(mActivePointerId); mLastTouchX = ev.getX(tempPointerIndex); mLastTouchY = ev.getY(tempPointerIndex); } break; } } return true; }

Y aunque en su mayoría no está relacionado, aquí está el ScaleListener:

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); invalidate(); return true; } }

De nuevo, este código NO funciona a la perfección, pero está muy cerca. Le expliqué el problema exacto anterior y sigo teniendo problemas para hacerlo funcionar. No sé si esto aparecerá en sus notificaciones, Hank, pero espero que alguien lo vea y me ayude.


La solución de Hank funciona para mí. Agregué una función de reinicio para que las imágenes subsiguientes puedan mostrarse normalmente.

public void ResetView() { mScaleFactor = 1.f; mPosX = 0.f; mPosY = 0.f; }


Sin mirar el código, asumiría que estás haciendo un cálculo de posición basado en 2 dedos cuando hay 2 dedos. Siempre obtendrás un salto en ese caso.