Come posso ottenere la funzionalità di zoom per le immagini?


204

Esiste un modo comune per mostrare un'immagine grande e consentire all'utente di ingrandire, rimpicciolire e spostare l'immagine?

Fino ad ora ho trovato due modi:

  1. sovrascrivendo ImageView, questo sembra un po 'troppo per un problema così comune.
  2. usando una webview ma con meno controllo sul layout generale ecc.

C'è un CONTROLLO ZOOM (Widget) e puoi ascoltare l'evento OnTouch per gestire il panning.
tobrien,

1
Una domanda simile stackoverflow.com/questions/2537396/… , ha un link a questo tutorial anddev.org/… . Potrebbe esserti utile per fare una panoramica del tuo iamge. Non l'ho letto in dettaglio, ma potrebbe anche darti alcune idee su come fare anche la funzione di zoom.
Steve Haley,

Qualcuno ha provato a salvare l'immagine durante lo zoom? Voglio che l'immagine salvata sia su uno stato predefinito anziché su uno zoom. Si prega di vedere la mia domanda: stackoverflow.com/questions/24730793/… Grazie
Blaze Tama,

Risposte:


208

AGGIORNARE

Ho appena dato a TouchImageView un nuovo aggiornamento. Ora include Zoom doppio tocco e Fling oltre a Panoramica e Zoom pizzico. Il codice seguente è molto datato. Puoi dare un'occhiata al progetto github per ottenere l'ultimo codice.

USO

Inserisci TouchImageView.java nel tuo progetto. Può quindi essere usato come ImageView. Esempio:

TouchImageView img = (TouchImageView) findViewById(R.id.img);

Se si utilizza TouchImageView in xml, è necessario fornire il nome completo del pacchetto, poiché è una vista personalizzata. Esempio:

<com.example.touch.TouchImageView
    android:id="@+id/img”
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Nota: ho rimosso la mia risposta precedente, che includeva un codice molto vecchio e ora mi collego direttamente al codice più aggiornato su github.

ViewPager

Se sei interessato a inserire TouchImageView in un ViewPager, fai riferimento a questa risposta.


4
Paulo, non ho riscontrato problemi di prestazioni, ma non sono riuscito a provare su un tablet. Per lento, intendi ritardato? Ho impostato un fattore di zoom massimo di 1,05 all'inizio di onScale. È di questo che stai parlando? In caso contrario, prova quanto segue: 1. Sei in modalità debug? Ciò rallenterebbe in modo significativo. 2. Quali immagini dimensioni stai impostando. Non ho testato con immagini molto grandi (8mp), ma questo potrebbe rallentarlo. 3. Hai un telefono su cui puoi provare? 4. Se tutto il resto fallisce, vedi se moltiplicare mScaleFactor per 2 (se> 1) o 0,5 (se <1) aiuta la tua situazione.
Mike Ortiz,

3
@Ahsan Cambia il costruttore della vista in: TouchImageView(Context context, AttributeSet attrs)e chiama super(context, attrs);Questo perché quando si gonfia la vista personalizzata, viene costruita con due parametri, anziché solo uno. Quando ci arrivo, riparerò TouchImageView per supportare i tre costruttori di vista e disegni.
Mike Ortiz,

2
@Ahsan Poiché si tratta di una vista personalizzata, è necessario scrivere l'intero nome nel file XML, ad es <com.example.TouchImageView android:id="@+id/img" />. Sei stato tu?
Mike Ortiz,

1
Questa è roba fantastica, la stavo cercando da secoli. Usa il codice di Github in quanto è più recente e funziona meglio
Alex

2
@Mike ho provato questo codice ma la galleria personalizzata non funziona. C'è qualche trucco per aggirare questo problema.
Umesh,

80

Ho adattato del codice per creare un TouchImageView che supporti il ​​multitouch (> 2.1). È ispirato al libro Ciao, Android! (3a edizione)

È contenuto nei seguenti 3 file TouchImageView.java WrapMotionEvent.java EclairMotionEvent.java

TouchImageView.java

import se.robertfoss.ChanImageBrowser.Viewer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class TouchImageView extends ImageView {

    private static final String TAG = "Touch";
    // These matrices will be used to move and zoom image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new 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 start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;

    Context context;


    public TouchImageView(Context context) {
        super(context);
        super.setClickable(true);
        this.context = context;

        matrix.setTranslate(1f, 1f);
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent rawEvent) {
                WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent);

                // Dump touch event to log
                if (Viewer.isDebug == true){
                    dumpEvent(event);
                }

                // Handle touch events here...
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    savedMatrix.set(matrix);
                    start.set(event.getX(), event.getY());
                    Log.d(TAG, "mode=DRAG");
                    mode = DRAG;
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = spacing(event);
                    Log.d(TAG, "oldDist=" + oldDist);
                    if (oldDist > 10f) {
                        savedMatrix.set(matrix);
                        midPoint(mid, event);
                        mode = ZOOM;
                        Log.d(TAG, "mode=ZOOM");
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    int xDiff = (int) Math.abs(event.getX() - start.x);
                    int yDiff = (int) Math.abs(event.getY() - start.y);
                    if (xDiff < 8 && yDiff < 8){
                        performClick();
                    }
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    Log.d(TAG, "mode=NONE");
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == DRAG) {
                        // ...
                        matrix.set(savedMatrix);
                        matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
                    } else if (mode == ZOOM) {
                        float newDist = spacing(event);
                        Log.d(TAG, "newDist=" + newDist);
                        if (newDist > 10f) {
                            matrix.set(savedMatrix);
                            float scale = newDist / oldDist;
                            matrix.postScale(scale, scale, mid.x, mid.y);
                        }
                    }
                    break;
                }

                setImageMatrix(matrix);
                return true; // indicate event was handled
            }

        });
    }


    public void setImage(Bitmap bm, int displayWidth, int displayHeight) { 
        super.setImageBitmap(bm);

        //Fit to screen.
        float scale;
        if ((displayHeight / bm.getHeight()) >= (displayWidth / bm.getWidth())){
            scale =  (float)displayWidth / (float)bm.getWidth();
        } else {
            scale = (float)displayHeight / (float)bm.getHeight();
        }

        savedMatrix.set(matrix);
        matrix.set(savedMatrix);
        matrix.postScale(scale, scale, mid.x, mid.y);
        setImageMatrix(matrix);


        // Center the image
        float redundantYSpace = (float)displayHeight - (scale * (float)bm.getHeight()) ;
        float redundantXSpace = (float)displayWidth - (scale * (float)bm.getWidth());

        redundantYSpace /= (float)2;
        redundantXSpace /= (float)2;


        savedMatrix.set(matrix);
        matrix.set(savedMatrix);
        matrix.postTranslate(redundantXSpace, redundantYSpace);
        setImageMatrix(matrix);
    }


    /** Show an event in the LogCat view, for debugging */
    private void dumpEvent(WrapMotionEvent event) {
        // ...
        String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
            "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
        StringBuilder sb = new StringBuilder();
        int action = event.getAction();
        int actionCode = action & MotionEvent.ACTION_MASK;
        sb.append("event ACTION_").append(names[actionCode]);
        if (actionCode == MotionEvent.ACTION_POINTER_DOWN
                || actionCode == MotionEvent.ACTION_POINTER_UP) {
            sb.append("(pid ").append(
                    action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
            sb.append(")");
        }
        sb.append("[");
        for (int i = 0; i < event.getPointerCount(); i++) {
            sb.append("#").append(i);
            sb.append("(pid ").append(event.getPointerId(i));
            sb.append(")=").append((int) event.getX(i));
            sb.append(",").append((int) event.getY(i));
            if (i + 1 < event.getPointerCount())
            sb.append(";");
        }
        sb.append("]");
        Log.d(TAG, sb.toString());
    }

    /** Determine the space between the first two fingers */
    private float spacing(WrapMotionEvent event) {
        // ...
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, WrapMotionEvent event) {
        // ...
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }
}

WrapMotionEvent.java

import android.view.MotionEvent;

public class WrapMotionEvent {
protected MotionEvent event;




    protected WrapMotionEvent(MotionEvent event) {
        this.event = event;
    }

    static public WrapMotionEvent wrap(MotionEvent event) {
            try {
                return new EclairMotionEvent(event);
            } catch (VerifyError e) {
                return new WrapMotionEvent(event);
            }
    }



    public int getAction() {
            return event.getAction();
    }

    public float getX() {
            return event.getX();
    }

    public float getX(int pointerIndex) {
            verifyPointerIndex(pointerIndex);
            return getX();
    }

    public float getY() {
            return event.getY();
    }

    public float getY(int pointerIndex) {
            verifyPointerIndex(pointerIndex);
            return getY();
    }

    public int getPointerCount() {
            return 1;
    }

    public int getPointerId(int pointerIndex) {
            verifyPointerIndex(pointerIndex);
            return 0;
    }

    private void verifyPointerIndex(int pointerIndex) {
            if (pointerIndex > 0) {
                throw new IllegalArgumentException(
                    "Invalid pointer index for Donut/Cupcake");
            }
    }

}

EclairMotionEvent.java

import android.view.MotionEvent;

public class EclairMotionEvent extends WrapMotionEvent {

    protected EclairMotionEvent(MotionEvent event) {
            super(event);
    }

    public float getX(int pointerIndex) {
            return event.getX(pointerIndex);
    }

    public float getY(int pointerIndex) {
            return event.getY(pointerIndex);
    }

    public int getPointerCount() {
            return event.getPointerCount();
    }

    public int getPointerId(int pointerIndex) {
            return event.getPointerId(pointerIndex);
    }
}

Robert Foss, se questo aggiunge un giudice di frontiera, può andare meglio. Grazie molto bene il tuo codice
pengwang

3
Funziona, ma non vedo il punto in WrapMotionEvente EclairMotionEvent... comunque, +1.
Cipi,

2
Multitouch per telefoni che lo supportano. Un tocco regolare per Android <2.0
Robert Foss

Un bell'esempio funziona benissimo ma non ho trovato in cosa Viewer if (Viewer.isDebug == true) {dumpEvent (event); }
Tofeeq Ahmad,

2
Cos'è questo? >> se.robertfoss.ChanImageBrowser.Viewer
emeraldhieu

60

Ho usato un WebView e caricato l'immagine dalla memoria tramite

webview.loadUrl("file://...")

WebView gestisce tutto lo zoom e lo scorrimento del panning. Se usi wrap_content la visualizzazione web non sarà più grande quindi l'immagine e non verranno visualizzate aree bianche. Il WebView è il migliore ImageView;)


5
Sto usando lo stesso approccio. Ho una grande mappa della metropolitana che voglio che l'utente sia in grado di ingrandire e scorrere. Ho notato, tuttavia, che se si dispone di un'immagine abbastanza grande (ovvero 1000 o 3000 pixel di larghezza), l'immagine diventa sfocata quando si ingrandisce. Sembra che Coliris non possa visualizzare un'immagine ingrandita di grandi dimensioni molto nitida. Anche se l'immagine originale è non compressa e molto nitida. Quindi ho finito per tagliare l'immagine grande in sezioni più piccole e rimetterle insieme via HTML. In questo modo l'immagine rimane nitida durante lo zoom. (Sono su Nexus One, 2.1 aggiornato prima e ora su 2.2)
Mathias Conradt,

@Mathias Lin: se un'immagine grande viene inviata via cavo, ho sentito che i portatori comprimono immagini grandi. questa custodia sarà adatta a te o hai caricato l'immagine localmente?
Samuel,

@Sam Quest: caricandolo localmente
Mathias Conradt,

4
molto meglio usare i pulsanti zoom integrati di webview e il supporto per pizzicare per ingrandire / ridurre piuttosto che scrivere un algo completamente nuovo che potrebbe non funzionare su telefoni diversi e versioni future della piattaforma Android
sami,

2
questa soluzione può essere applicata solo se ti capita di avere l'immagine seduta sul disco, o l'immagine è abbastanza piccola da poter basare la codifica 64 e passare il valore della stringa in loadUrlWithData ().
Jeffrey Blattman,

7

In risposta alla domanda originale di Janusz, ci sono diversi modi per raggiungere questo obiettivo che variano nel loro livello di difficoltà e sono stati indicati di seguito. L'utilizzo di una visualizzazione Web è buono, ma è molto limitato in termini di aspetto grafico e controllabilità. Se stai disegnando una bitmap da una tela, le soluzioni più versatili che sono state proposte sembrano essere quelle di MikeOrtiz, Robert Foss e / o ciò che Jacob Nordfalk ha suggerito. C'è un ottimo esempio per incorporare il controller multitouch per Android di PaulBourke ed è ottimo per avere il supporto multi-touch e tutti i tipi di visualizzazioni personalizzate.

Personalmente, se stai semplicemente disegnando una tela su una bitmap e poi la visualizzi all'interno e su ImageView e vuoi essere in grado di ingrandire e spostarti utilizzando il multi-touch, trovo la soluzione di MikeOrtiz come la più semplice. Tuttavia, per i miei scopi, il codice di Git che ha fornito sembra funzionare solo quando la sua classe ImageView personalizzata TouchImageView è l'unica figlia o fornisce i parametri di layout come:

android:layout_height="match_parent"
android:layout_height="match_parent"

Sfortunatamente a causa del mio design del layout, avevo bisogno di "wrap_content" per "layout_height". Quando l'ho cambiato in questo, l'immagine è stata ritagliata in basso e non ho potuto scorrere o ingrandire l'area ritagliata. Quindi ho dato un'occhiata a Source per ImageView solo per vedere come Android implementasse "onMeasure" e cambiò quello di MikeOrtiz per adattarlo.

   @Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

  //**** ADDED THIS ********/////
      int  w = (int) bmWidth;
      int  h = (int) bmHeight;
     width = resolveSize(w, widthMeasureSpec);  
     height = resolveSize(h, heightMeasureSpec);
  //**** END ********///   

   // width = MeasureSpec.getSize(widthMeasureSpec);   // REMOVED
   // height = MeasureSpec.getSize(heightMeasureSpec); // REMOVED

    //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;
   // origHeight = bmHeight;
    right = width * saveScale - width - (2 * redundantXSpace * saveScale);
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);

    setImageMatrix(matrix);
}

ResolSize (int, int) è un'utilità per riconciliare una dimensione desiderata con i vincoli imposti da MeasureSpec, dove:

parametri:

 - size How big the view wants to be
 - MeasureSpec Constraints imposed by the parent

Ritorna:

 - The size this view should be."

Quindi essenzialmente fornendo un comportamento un po 'più simile alla classe ImageView originale quando l'immagine viene caricata. Alcune ulteriori modifiche potrebbero essere apportate per supportare una maggiore varietà di schermi che modificano le proporzioni. Ma per ora spero che questo aiuti. Grazie a MikeOrtiz per il suo codice originale, ottimo lavoro.


Questa correzione è stata incorporata nel repository github di Mike?
LarsH,


6

Ho appena integrato TouchImageView di Robert Foss: ha funzionato alla perfezione! Grazie!

Ho appena modificato un po 'il codice in modo da poterlo istanziare dal mio layout.xml.

Aggiungi solo due costruttori

public TouchImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public TouchImageView(Context context) {
    super(context);
    init(context);
}

e trasforma il vecchio costruttore in un metodo init:

private void init(Context context){
    //...old code ofconstructor of Robert Moss's code
}

3

@Robert Foss, @Mike Ortiz, grazie mille per il tuo lavoro. Ho unito il tuo lavoro e ho completato le lezioni di Robert per Android> 2.0 con il lavoro aggiuntivo di Mike.

Come risultato del mio lavoro, presento Android Touch Gallery, basato su ViewPager e TouchImageView modificato. Le immagini si caricano tramite URL e puoi ingrandirle e trascinarle. Puoi trovarlo qui https://github.com/Dreddik/AndroidTouchGallery



2

Aggiungendo alla risposta di @ Mike. Ho anche bisogno di un doppio tocco per ripristinare l'immagine alle dimensioni originali alla prima visualizzazione. Quindi ho aggiunto un mucchio di variabili di istanza "orig ..." e ho aggiunto SimpleOnGestureListener che ha funzionato.

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;

public class TouchImageView extends ImageView {

    Matrix matrix = new 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;

    float redundantXSpace, redundantYSpace, origRedundantXSpace, origRedundantYSpace;;

    float width, height;
    static final int CLICK = 3;
    static final float SAVE_SCALE = 1f;
    float saveScale = SAVE_SCALE;

    float right, bottom, origWidth, origHeight, bmWidth, bmHeight, origScale, origBottom,origRight;

    ScaleGestureDetector mScaleDetector;
    GestureDetector mGestureDetector;

    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) {

                boolean onDoubleTapEvent = mGestureDetector.onTouchEvent(event);
                if (onDoubleTapEvent) {
                    // Reset Image to original scale values
                    mode = NONE;
                    bottom = origBottom;
                    right = origRight;
                    last = new PointF();
                    start = new PointF();
                    m = new float[9];
                    saveScale = SAVE_SCALE;
                    matrix = new Matrix();
                    matrix.setScale(origScale, origScale);
                    matrix.postTranslate(origRedundantXSpace, origRedundantYSpace);
                    setImageMatrix(matrix);
                    invalidate();
                    return true;
                } 


                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
            }

        });

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                return true;
            }
        });
    }

    @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 = SAVE_SCALE;
        origScale = scale;

        // Center the image
        redundantYSpace = (float) height - (scale * (float) bmHeight);
        redundantXSpace = (float) width - (scale * (float) bmWidth);
        redundantYSpace /= (float) 2;
        redundantXSpace /= (float) 2;

        origRedundantXSpace = redundantXSpace;
        origRedundantYSpace = redundantYSpace;

        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);
        origRight = right;
        origBottom = bottom;
        setImageMatrix(matrix);
    }

}

2

Questa è un'aggiunta molto recente a questo thread, ma ho lavorato su una visualizzazione di immagini che supporta zoom e pan e ha un paio di funzionalità che non ho trovato altrove. Questo è iniziato come un modo per visualizzare immagini molto grandi senza causare OutOfMemoryErrors, ricampionando l'immagine durante lo zoom indietro e caricando i riquadri a risoluzione più elevata quando ingrandito. Ora supporta l'uso in a ViewPager, rotazione manuale o utilizzando informazioni EXIF ​​(90 ° stop), sovrascrivi gli eventi tocco selezionati usando OnClickListenero il tuo GestureDetectoro OnTouchListener, sottoclasse per aggiungere sovrapposizioni, panoramica durante lo zoom e slancio.

Non è inteso come un sostituto per uso generale, ImageViewquindi non lo estende e non supporta la visualizzazione di immagini da risorse, solo risorse e file esterni. Richiede SDK 10.

La fonte è su GitHub e c'è un esempio che illustra l'uso in a ViewPager.

https://github.com/davemorrissey/subsampling-scale-image-view


1

Puoi provare a usare LayoutParams per questo

public void zoom(boolean flag){
    if(flag){
        int width=40;
        int height=40;
    }
    else{
        int width=20;
        int height=20;
    }
    RelativeLayout.LayoutParams param=new RelativeLayout.LayoutParams(width,height); //use the parent layout of the ImageView;
    imageView.setLayoutParams(param); //imageView is the view which needs zooming.
}

ZoomIn = zoom (vero); ZoomOut = zoom (false);


0
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageDetail = (ImageView) findViewById(R.id.imageView1);
    imageDetail.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            ImageView view = (ImageView) v;
            System.out.println("matrix=" + savedMatrix.toString());
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    savedMatrix.set(matrix);
                    startPoint.set(event.getX(), event.getY());
                    mode = DRAG;
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = spacing(event);
                    if (oldDist > 10f) {
                        savedMatrix.set(matrix);
                        midPoint(midPoint, event);
                        mode = ZOOM;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == DRAG) {
                        matrix.set(savedMatrix);
                        matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);
                    } else if (mode == ZOOM) {
                        float newDist = spacing(event);
                        if (newDist > 10f) {
                            matrix.set(savedMatrix);
                            float scale = newDist / oldDist;
                            matrix.postScale(scale, scale, midPoint.x, midPoint.y);
                        }
                    }
                    break;
            }
            view.setImageMatrix(matrix);
            return true;

        }

        @SuppressLint("FloatMath")
        private float spacing(MotionEvent event) {
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            return FloatMath.sqrt(x * x + y * y);
        }

        private void midPoint(PointF point, MotionEvent event) {
            float x = event.getX(0) + event.getX(1);
            float y = event.getY(0) + event.getY(1);
            point.set(x / 2, y / 2);
        }
    });
}

e la cartella disegnabile dovrebbe avere un file immagine bticn. funziona perfettamente :)


0

Qualcosa come sotto lo farà.

@Override public boolean onTouch(View v,MotionEvent e)
{

    tap=tap2=drag=pinch=none;
    int mask=e.getActionMasked();
    posx=e.getX();posy=e.getY();

    float midx= img.getWidth()/2f;
    float midy=img.getHeight()/2f;
    int fingers=e.getPointerCount();

    switch(mask)
    {
        case MotionEvent.ACTION_POINTER_UP:
            tap2=1;break;

        case MotionEvent.ACTION_UP:
            tap=1;break;

        case MotionEvent.ACTION_MOVE:
            drag=1;
    }
    if(fingers==2){nowsp=Math.abs(e.getX(0)-e.getX(1));}
    if((fingers==2)&&(drag==0)){ tap2=1;tap=0;drag=0;}
    if((fingers==2)&&(drag==1)){ tap2=0;tap=0;drag=0;pinch=1;}

    if(pinch==1)

    {
        if(nowsp>oldsp)scale+=0.1;
        if(nowsp<oldsp)scale-=0.1;
        tap2=tap=drag=0;    
    }
    if(tap2==1)
        {
            scale-=0.1;
            tap=0;drag=0;
        }
    if(tap==1)
        {
            tap2=0;drag=0;
            scale+=0.1;
        }
    if(drag==1)
        {
            movx=posx-oldx;
            movy=posy-oldy;
            x+=movx;
            y+=movy;
            tap=0;tap2=0;
        }
    m.setTranslate(x,y);
    m.postScale(scale,scale,midx,midy);
    img.setImageMatrix(m);img.invalidate();
    tap=tap2=drag=none;
    oldx=posx;oldy=posy;
    oldsp=nowsp;
    return true;
}


public void onCreate(Bundle b)
{
        super.onCreate(b);

    img=new ImageView(this);
    img.setScaleType(ImageView.ScaleType.MATRIX);
    img.setOnTouchListener(this);

    path=Environment.getExternalStorageDirectory().getPath();   
    path=path+"/DCIM"+"/behala.jpg";
    byte[] bytes;
    bytes=null;
    try{
        FileInputStream fis;
        fis=new FileInputStream(path);
        BufferedInputStream bis;
        bis=new BufferedInputStream(fis);
        bytes=new byte[bis.available()];
        bis.read(bytes);
        if(bis!=null)bis.close();
        if(fis!=null)fis.close();

     }
    catch(Exception e)
        {
        ret="Nothing";
        }
    Bitmap bmp=BitmapFactory.decodeByteArray(bytes,0,bytes.length);

    img.setImageBitmap(bmp);

    setContentView(img);
}

Per visualizzare il programma completo vedere qui: Programma per ingrandire l'immagine in Android

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.