¿Se puede usar el detector de gestos de escala para pellizcar el zoom en Android?¿Se puede usar el detector de gestos de escala para pellizcar el zoom en Android?
Respuesta
Puede utilizar esta
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
public class MyImageView extends View {
private static final int INVALID_POINTER_ID = -1;
private Drawable mImage;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
public MyImageView(Context context) {
this(context, null, 0);
mImage=act.getResources().getDrawable(context.getResources().getIdentifier("imagename", "drawable", "packagename"));
mImage.setBounds(0, 0, mImage.getIntrinsicWidth(), mImage.getIntrinsicHeight());
}
public MyImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
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: {
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();
Log.d("DEBUG", "X: "+mPosX+" Y: "+mPosY);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
mImage.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, 10.0f));
invalidate();
return true;
}
}
}
llamar a esto en su ScaleGestureDetector activity.setContentView(new MyImageView(this));
está disponible a partir de Android 2.2 (también conocido como Froyo, el nivel de API 8). Ve: http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html
En 2.0/2.1, que no tienen ScaleGestureDetector, pero no puede suministrar pellizcar para hacer zoom mediante la entrada de blog de ZDNet por Ed Burnette que Pieter888 vinculada a arriba: http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847
sí se puede aquí es donde el código de ejemplo onPinch() y onZoom() son las acciones a implementar por su cuenta
public class simpleOnScaleGestureListener extends
SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
startScale = detector.getScaleFactor();
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
endScale = detector.getScaleFactor();
// if ((startScale - endScale) > 0.0100
// || (endScale - startScale) > 0.0100) {
if (startScale > endScale) {
Log.i("onScaleEnd", "Pinch Dection");
onPinch();
} else if (startScale < endScale) {
Log.i("onScaleEnd", "Zoom Dection");
onZoom();
}
// }
}
}
? Creo que está dejando demasiado para que esta respuesta sea útil. Este es solo su ScaleGestureListener, ¿y el resto? –
he llamado a onpinch() y onzoom() que tiene la implementación de pinchzoom en mi customeview puede implementar su propio – AMD
que no funciona para mí. las condiciones no pasan; – MSaudi
realidad hay una biblioteca que utiliza esta clase sólo para el zoom de las imágenes.
Se llama "TouchImageView"
Puede crear una clase reutilizable que implementa OnTouchListener
para lograr esto.
public class MyScaleGestures implements OnTouchListener, OnScaleGestureListener {
private View view;
private ScaleGestureDetector gestureScale;
private float scaleFactor = 1;
public StandardGestures(Context c){ gestureScale = new ScaleGestureDetector(c, this); }
@Override
public boolean onTouch(View view, MotionEvent event) {
this.view = view;
gestureScale.onTouchEvent(event);
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
scaleFactor = (scaleFactor < 1 ? 1 : scaleFactor); // prevent our view from becoming too small //
scaleFactor = ((float)((int)(scaleFactor * 100)))/100; // Change precision to help with jitter when user just rests their fingers //
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
inScale = true;
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) { inScale = false; }
}
A continuación, asigne como sus View
's OnTouchListener
como tal.
myView.setOnTouchListener(new MyScaleGestures(context));
Si desea agregar una capacidad de desplazamiento a la View
tendrá que aplicar onScroll
. Puede agregar esta anulación a la clase MyScaleGestures
para lograr esto.
@Override
public boolean onScroll(MotionEvent event1, MotionEvent event2, float x, float y) {
float newX = view.getX();
float newY = view.getY();
if(!inScale){
newX -= x;
newY -= y;
}
WindowManager wm = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
Point p = new Point();
d.getSize(p);
if (newX > (view.getWidth() * scaleFactor - p.x)/2){
newX = (view.getWidth() * scaleFactor - p.x)/2;
} else if (newX < -((view.getWidth() * scaleFactor - p.x)/2)){
newX = -((view.getWidth() * scaleFactor - p.x)/2);
}
if (newY > (view.getHeight() * scaleFactor - p.y)/2){
newY = (view.getHeight() * scaleFactor - p.y)/2;
} else if (newY < -((view.getHeight() * scaleFactor - p.y)/2)){
newY = -((view.getHeight() * scaleFactor - p.y)/2);
}
view.setX(newX);
view.setY(newY);
return true;
}
Después de escalar, no puedo mover la imagen para leer el contenido que sale de la pantalla debido a la escala. –
@shriduttkothari Correcto, este código no escucha el gesto de desplazamiento. Tendrá que implementar 'onScroll' para mover a la vista. – ChrisStillwell
por favor, ¿puedes dar un ejemplo? –
TouchImageView
public class TouchImageView extends ImageView {
Matrix matrix;
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
int viewWidth, viewHeight;
static final int CLICK = 3;
float saveScale = 1f;
protected float origWidth, origHeight;
int oldMeasuredWidth, oldMeasuredHeight;
ScaleGestureDetector mScaleDetector;
Context context;
public TouchImageView(Context context) {
super(context);
sharedConstructing(context);
}
public TouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
sharedConstructing(context);
}
private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix = new Matrix();
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(curr);
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);
matrix.postTranslate(fixTransX, fixTransY);
fixTrans();
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true; // indicate event was handled
}
});
}
public void setMaxZoom(float x) {
maxScale = x;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale) {
saveScale = maxScale;
mScaleFactor = maxScale/origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale/origScale;
}
if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
matrix.postScale(mScaleFactor, mScaleFactor, viewWidth/2, viewHeight/2);
else
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
fixTrans();
return true;
}
}
void fixTrans() {
matrix.getValues(m);
float transX = m[Matrix.MTRANS_X];
float transY = m[Matrix.MTRANS_Y];
float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);
if (fixTransX != 0 || fixTransY != 0)
matrix.postTranslate(fixTransX, fixTransY);
}
float getFixTrans(float trans, float viewSize, float contentSize) {
float minTrans, maxTrans;
if (contentSize <= viewSize) {
minTrans = 0;
maxTrans = viewSize - contentSize;
} else {
minTrans = viewSize - contentSize;
maxTrans = 0;
}
if (trans < minTrans)
return -trans + minTrans;
if (trans > maxTrans)
return -trans + maxTrans;
return 0;
}
float getFixDragTrans(float delta, float viewSize, float contentSize) {
if (contentSize <= viewSize) {
return 0;
}
return delta;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
//
// Rescales image on rotation
//
if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
|| viewWidth == 0 || viewHeight == 0)
return;
oldMeasuredHeight = viewHeight;
oldMeasuredWidth = viewWidth;
if (saveScale == 1) {
//Fit to screen.
float scale;
Drawable drawable = getDrawable();
if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)
return;
int bmWidth = drawable.getIntrinsicWidth();
int bmHeight = drawable.getIntrinsicHeight();
Log.e("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);
float scaleX = (float) viewWidth/(float) bmWidth;
float scaleY = (float) viewHeight/(float) bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
// Center the image
float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);
float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);
redundantYSpace /= (float) 2;
redundantXSpace /= (float) 2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = viewWidth - 2 * redundantXSpace;
origHeight = viewHeight - 2 * redundantYSpace;
setImageMatrix(matrix);
}
fixTrans();
}
}
MainActivity.java
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
TouchImageView img = new TouchImageView(this);
img.setImageResource(R.drawable.ic_launcher);
img.setMaxZoom(4f);
setContentView(img);
}
}
- 1. android pellizcar zoom
- 2. Implementando Pellizcar y Zoom en Android SurfaceView
- 3. pellizcar el zoom para vista personalizada
- 4. pellizcar el zoom para la vista de texto
- 5. Límites de escala en el zoom de pellizco de Android
- 6. Android web vista pellizcar zoom Problema
- 7. Deshabilitar pellizcar zoom en WebView?
- 8. ¿Cómo habilitar los controles de zoom y pellizcar el zoom en un WebView?
- 9. Toque dos veces para acercar y pellizcar para hacer zoom en ImageView en android
- 10. Lienzo pellizcar-Zoom a punto dentro de los límites
- 11. ¿Hay una API incorporada para manejar la funcionalidad de pellizcar-zoom en Android
- 12. Pellizcar Acercar vista web [Android]
- 13. ios - Pellizcar/acercar con la escala actual
- 14. ¿Cómo se obtiene la escala de ventana gráfica después de pellizcar/acercar en una aplicación web de iPhone?
- 15. Detección de escala de zoom de iPad
- 16. iPhone google maps v3 sartenes después de pellizcar zoom
- 17. Reconocimiento de gestos en Android
- 18. ImageView Pinch-zoom Límites de escala y límites de panorámica
- 19. detectando pellizcar para ampliar en iOS
- 20. Jquery que se puede arrastrar con el problema de zoom
- 21. ¿No se puede usar el spinner de Android?
- 22. Pinch/especificación de vista de zoom funciona en el iPhone, pero no en Android
- 23. Android: RadioGroup - Como configurar el detector de eventos
- 24. Android: detección de gestos arrojadizos
- 25. ¿Hacer zoom en el navegador es lo mismo que hacer zoom en un dispositivo móvil?
- 26. ¿Cómo restablezco la escala/el zoom de una aplicación web en un cambio de orientación en el iPhone?
- 27. Cómo utilizar el mapa de Android para hacer zoom con gesto con la mano (como el iphone)
- 28. botones de zoom en el navegador web de Android
- 29. No se puede usar el teclado en el emulador de Android
- 30. UIWebView: cargue el sitio web externo, establezca la escala de zoom inicial programáticamente y permita al usuario hacer zoom posteriormente
en reducir el zoom que le lleva al punto 0,0. no hace zoom en el punto inicial de tus dedos. ¿por qué es así? – sajjoo
sajjoo: Creo que puedes hacerlo usando 'ScaleGestureDetector.getFocusX, Y()' – Timmmm
Intenté esto pero el zoom es muy insensible y entrecortado (estoy dibujando líneas en el lienzo mediante programación). ¿Alguna idea de por qué? – Rookatu