¿Cómo funciona TouchImageView?

Tengo buen funcionamiento TouchImageView y quiero saber cómo funciona en un código: Lo que sólo quiero hacer es ser capaz de pellizcar a un zoom, o utilizar el doble toque para ampliar cualquier imagen que yo elija, y cuando hago zoom de nuevo i Volver al tamaño original de la imagen. TouchImageView.java:

public class TouchImageView extends ImageView { Matrix matrix = new Matrix(); static final int NONE = 0; static final int DRAG = 1; static final int ZOOM = 2; int mode = NONE; PointF last = new PointF(); PointF start = new PointF(); float minScale = 1f; float maxScale = 3f; float[] m; float redundantXSpace, redundantYSpace; float width, height; static final int CLICK = 3; float saveScale = 1f; float right, bottom, origWidth, origHeight, bmWidth, bmHeight; ScaleGestureDetector mScaleDetector; Context context; public TouchImageView(Context context) { super(context); super.setClickable(true); this.context = context; mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); matrix.setTranslate(1f, 1f); m = new float[9]; setImageMatrix(matrix); setScaleType(ScaleType.MATRIX); setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mScaleDetector.onTouchEvent(event); matrix.getValues(m); float x = m[Matrix.MTRANS_X]; float y = m[Matrix.MTRANS_Y]; PointF curr = new PointF(event.getX(), event.getY()); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: last.set(event.getX(), event.getY()); 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 scaleWidth = Math.round(origWidth * saveScale); float scaleHeight = Math.round(origHeight * saveScale); if (scaleWidth < width) { deltaX = 0; if (y + deltaY > 0) deltaY = -y; else if (y + deltaY < -bottom) deltaY = -(y + bottom); } else if (scaleHeight < height) { deltaY = 0; if (x + deltaX > 0) deltaX = -x; else if (x + deltaX < -right) deltaX = -(x + right); } else { if (x + deltaX > 0) deltaX = -x; else if (x + deltaX < -right) deltaX = -(x + right); if (y + deltaY > 0) deltaY = -y; else if (y + deltaY < -bottom) deltaY = -(y + bottom); } matrix.postTranslate(deltaX, deltaY); 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 } }); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); bmWidth = bm.getWidth(); bmHeight = bm.getHeight(); } 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 = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05); float origScale = saveScale; saveScale *= mScaleFactor; if (saveScale > maxScale) { saveScale = maxScale; mScaleFactor = maxScale / origScale; } else if (saveScale < minScale) { saveScale = minScale; mScaleFactor = minScale / origScale; } right = width * saveScale - width - (2 * redundantXSpace * saveScale); bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); if (origWidth * saveScale <= width || origHeight * saveScale <= height) { matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2); if (mScaleFactor < 1) { matrix.getValues(m); float x = m[Matrix.MTRANS_X]; float y = m[Matrix.MTRANS_Y]; if (mScaleFactor < 1) { if (Math.round(origWidth * saveScale) < width) { if (y < -bottom) matrix.postTranslate(0, -(y + bottom)); else if (y > 0) matrix.postTranslate(0, -y); } else { if (x < -right) matrix.postTranslate(-(x + right), 0); else if (x > 0) matrix.postTranslate(-x, 0); } } } } else { matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); matrix.getValues(m); float x = m[Matrix.MTRANS_X]; float y = m[Matrix.MTRANS_Y]; if (mScaleFactor < 1) { if (x < -right) matrix.postTranslate(-(x + right), 0); else if (x > 0) matrix.postTranslate(-x, 0); if (y < -bottom) matrix.postTranslate(0, -(y + bottom)); else if (y > 0) matrix.postTranslate(0, -y); } } return true; } } @Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); height = MeasureSpec.getSize(heightMeasureSpec); //Fit to screen. float scale; float scaleX = (float)width / (float)bmWidth; float scaleY = (float)height / (float)bmHeight; scale = Math.min(scaleX, scaleY); matrix.setScale(scale, scale); setImageMatrix(matrix); saveScale = 1f; // Center the image redundantYSpace = (float)height - (scale * (float)bmHeight) ; redundantXSpace = (float)width - (scale * (float)bmWidth); redundantYSpace /= (float)2; redundantXSpace /= (float)2; matrix.postTranslate(redundantXSpace, redundantYSpace); origWidth = width - 2 * redundantXSpace; origHeight = height - 2 * redundantYSpace; right = width * saveScale - width - (2 * redundantXSpace * saveScale); bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); setImageMatrix(matrix); } } 

Para usar es que he creado una clase privada:

 private class CreateImage extends AsyncTask<String, Void, Drawable> { protected void onPreExecute() { } protected Drawable doInBackground(String... urls) { InputStream is; Drawable d = null ; try { is = (InputStream)new URL(urls[0]).getContent(); d = Drawable.createFromStream(is, "Image"); return d; } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return d; } protected void onPostExecute(Drawable d) { touch.setMaxZoom(4f); touch.setImageDrawable(d); setContentView(touch); } } public void createUrlImage(String url){ new CreateImage().execute(url); } 

Y en el onCreate () pongo createUrlImage (url). He modificado TouchImageView añadiendo:

 public void setImageDrawable(Drawable dr) { super.setImageDrawable(dr); bmWidth = dr.getIntrinsicWidth(); bmHeight = dr.getIntrinsicHeight(); } 

EDIT: Double Touch Zoom, Fling y otras características se han añadido a TouchImageView desde que respondí originalmente a esta pregunta. Usted puede comprobar hacia fuera en github aquí .


He añadido algunos detalles de uso a la publicación original aquí . El código ya tiene zoom pellizco y panning, junto con los límites. Además, el zoom hacia fuera le devolverá a la imagen de tamaño original.

La adición del zoom de doble toque requerirá más trabajo. Tendrás que usar un GestureDetector y anular onDoubleTap y onSingleTapConfirmed. A continuación, querrá asegurarse de que pasa sus eventos táctiles a gestureDetector, sin interferir con el resto del código (ver cómo se pasan los eventos a mScaleDetector al principio de onTouch). Desea deshacerse de la llamada a performClick () en ACTION_UP y en su lugar, colóquela en onSingleTapConfirmed. Puede comprobar esta respuesta para obtener algún código esquelético para empezar a implementar GestureDetector.

Déjeme saber si usted consigue conseguir el sólido del zumbido doble del golpecito y agregaré sus cambios al poste original y al repo de Github.

  • Devolución de llamada de la actividad en Córdoba
  • Detección de silencio de captura de audio de Android
  • Simple Thread Management - Java - Android
  • Android: ListView no muestra ningún resultado
  • Esperando hasta que la ubicación esté encendida después de encenderla a través de la alerta de servicios de ubicación
  • Entender la implementación de bloqueo personalizado en Android mediante la técnica de reemplazo de pantalla de inicio
  • Dagger 2 problema sobreponiendo único proporciona el método anotado de un módulo en una biblioteca que la aplicación utiliza
  • Cómo imprimir en la consola en Android Studio?
  • ¿Cuál es la forma correcta de implementar AsyncTask? Estática o no estática clase anidada?
  • Java - Crear referencia a dos modelos en un adaptador personalizado
  • Android: Crash en rotación, horizontal a vertical
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.