Wie erhalte ich die Zoomfunktion für Bilder?

Lesezeit: 12 Minuten

Wie erhalte ich die Zoomfunktion fur Bilder
Janusz

Gibt es eine gängige Methode, um ein großes Bild anzuzeigen und es dem Benutzer zu ermöglichen, das Bild zu vergrößern, zu verkleinern und zu schwenken?

Bisher habe ich zwei Wege gefunden:

  1. Überschreiben von ImageView, das scheint ein bisschen zu viel für ein so häufiges Problem zu sein.
  2. Verwenden einer Webansicht, aber mit weniger Kontrolle über das Gesamtlayout usw.

  • Es gibt eine ZOOM-STEUERUNG (Widget) und Sie können das OnTouch-Ereignis abhören, um das Schwenken zu handhaben.

    – Tobrien

    29. März 2010 um 13:33 Uhr

  • Eine ähnliche Frage, stackoverflow.com/questions/2537396/…, hat einen Link zu diesem Tutorial anddev.org/…. Sie finden das vielleicht nützlich, um Ihr Bild zu schwenken. Ich habe es nicht im Detail gelesen, aber es könnte Ihnen auch einige Ideen geben, wie Sie die Zoom-Funktion nutzen können.

    – Steve Haley

    29. März 2010 um 13:45 Uhr

  • Hat jemand versucht, das Bild beim Zoomen zu speichern? Ich möchte, dass das gespeicherte Bild einen Standardzustand anstelle des gezoomten Zustands hat. Siehe meine Frage: stackoverflow.com/questions/24730793/… Danke

    – Blaze Tama

    18. Juli 2014 um 5:00 Uhr

1646645592 619 Wie erhalte ich die Zoomfunktion fur Bilder
Mike Ortiz

AKTUALISIEREN

Ich habe gerade TouchImageView ein neues Update gegeben. Es enthält jetzt Double Tap Zoom und Fling zusätzlich zu Panning und Pinch Zoom. Der folgende Code ist sehr datiert. Sie können die überprüfen github-Projekt um den neuesten Code zu erhalten.

VERWENDUNGSZWECK

Platzieren Sie TouchImageView.java in Ihrem Projekt. Es kann dann genauso wie ImageView verwendet werden. Beispiel:

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

Wenn Sie TouchImageView in XML verwenden, müssen Sie den vollständigen Paketnamen angeben, da es sich um eine benutzerdefinierte Ansicht handelt. Beispiel:

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

Hinweis: Ich habe meine vorherige Antwort entfernt, die einen sehr alten Code enthielt, und verlinke jetzt direkt auf den aktuellsten Code auf GitHub.

ViewPager

Wenn Sie TouchImageView in einen ViewPager einfügen möchten, lesen Sie diese Antwort.

  • Paulo, ich hatte keine Leistungsprobleme, aber ich konnte es nicht auf einem Tablet testen. Meinst du mit langsam langsam? Ich habe zu Beginn von onScale einen maximalen Zoomfaktor von 1,05 eingestellt. Ist es das, wovon du sprichst? Wenn nicht, versuchen Sie Folgendes: 1. Befinden Sie sich im Debug-Modus? Dies würde es erheblich verlangsamen. 2. Welche Bildgröße stellen Sie ein? Ich habe nicht mit sehr großen (8 MP) Bildern getestet, aber das könnte es verlangsamen. 3. Haben Sie ein Telefon, auf dem Sie testen könnten? 4. Wenn alles andere fehlschlägt, prüfen Sie, ob die Multiplikation von mScaleFactor mit 2 (falls > 1) oder 0,5 (falls < 1) Ihrer Situation hilft.

    – Mike Ortiz

    4. Oktober 2011 um 0:51 Uhr

  • @Ahsan Ändern Sie den View-Konstruktor in: TouchImageView(Context context, AttributeSet attrs) und Ruf an super(context, attrs); Dies liegt daran, dass beim Aufblasen der benutzerdefinierten Ansicht diese mit zwei Parametern erstellt wird und nicht nur mit einem. Wenn ich dazu komme, werde ich TouchImageView reparieren, um die drei Ansichtskonstruktoren und Drawables zu unterstützen.

    – Mike Ortiz

    26. Oktober 2011 um 19:54 Uhr

  • @Ahsan Da es sich um eine benutzerdefinierte Ansicht handelt, müssen Sie den gesamten Namen in die XML-Datei schreiben, dh <com.example.TouchImageView android:id="@+id/img" />. Hast du das gemacht?

    – Mike Ortiz

    2. November 2011 um 5:56 Uhr

  • Das ist eine tolle Sache, suche schon seit Ewigkeiten danach. Verwenden Sie den Code von github, da er neuer ist und einfach besser funktioniert

    – Alex

    16. Juli 2012 um 18:20 Uhr

  • @Mike Ich habe diesen Code ausprobiert, aber die benutzerdefinierte Galerie funktioniert nicht. Gibt es einen Trick um dieses Problem zu umgehen.

    – Umesh

    4. Oktober 2012 um 6:36 Uhr

Ich habe etwas Code angepasst, um ein TouchImageView zu erstellen, das Multitouch unterstützt (>2.1). Es ist von dem Buch inspiriert Hallo Android! (3. Auflage)

Es ist in den folgenden 3 Dateien TouchImageView.java WrapMotionEvent.java EclairMotionEvent.java enthalten

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, wenn dieser Grenzrichter hinzufügt, kann es besser fallen. Vielen Dank für Ihren Code

    – pengwang

    2. Dezember 2010 um 7:20 Uhr

  • Es funktioniert, aber ich sehe keinen Sinn darin WrapMotionEvent und EclairMotionEvent… jedenfalls +1.

    – Cipi

    3. Juni 2011 um 14:27 Uhr

  • Multitouch für Telefone, die dies unterstützen. Eine regelmäßige Berührung für Android <2.0

    – Robert Foß

    8. Juli 2011 um 10:04 Uhr

  • Schönes Beispiel, es funktioniert gut, aber ich habe nicht bekommen, was Viewer ist, wenn (Viewer.isDebug == true) { dumpEvent (event); }

    – Tofeeq Ahmad

    6. April 2012 um 6:09 Uhr

  • Was ist das? >> se.robertfoss.ChanImageBrowser.Viewer

    – Smaragdhieu

    14. Mai 2012 um 6:51 Uhr

Wie erhalte ich die Zoomfunktion fur Bilder
Janusz

Ich habe ein WebView verwendet und das Bild aus dem Speicher geladen

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

Die WebView übernimmt das gesamte Schwenken, Zoomen und Scrollen. Wenn Sie wrap_content verwenden, wird die Webansicht nicht größer als das Bild und es werden keine weißen Bereiche angezeigt. Der WebView ist der bessere ImageView 😉

  • Ich verwende den gleichen Ansatz. Ich habe eine große U-Bahn-Karte, die der Benutzer zoomen und scrollen soll. Mir ist jedoch aufgefallen, dass bei einem ziemlich großen Bild (dh 1000 oder 3000 Pixel breit) das Bild verschwommen wird, sobald Sie hineinzoomen. Es scheint, dass Coliris ein großes gezoomtes Bild nicht sehr scharf anzeigen kann. Obwohl das Originalbild unkomprimiert und sehr scharf ist. Daher habe ich das eine große Bild in kleinere Scheiben geschnitten und per HTML wieder zusammengesetzt. So bleibt das Bild beim Hineinzoomen scharf. (Ich bin auf Nexus One, vorher 2.1update und jetzt auf 2.2)

    – Mathias Conradt

    15. Juni 2010 um 2:58 Uhr

  • @ Mathias Lin: Wenn ein großes Bild über die Leitung gesendet wird, habe ich gehört Träger Komprimieren Sie große Bilder. Passt dieser Anwendungsfall zu Ihnen oder haben Sie das Bild lokal geladen?

    – Samuel

    22. Februar 2011 um 4:42 Uhr

  • @Sam Quest: Laden Sie es lokal

    – Mathias Conradt

    22. Februar 2011 um 8:15 Uhr

  • Es ist viel besser, die integrierten Zoom-Schaltflächen von Webview und die Unterstützung für Pinch zum Vergrößern/Verkleinern zu verwenden, als einen völlig neuen Algo zu schreiben, der möglicherweise nicht auf verschiedenen Telefonen und zukünftigen Android-Plattformversionen funktioniert

    – samisch

    1. August 2011 um 5:52 Uhr

  • Diese Lösung kann nur angewendet werden, wenn Sie das Bild zufällig auf der Festplatte herumliegen haben oder das Bild klein genug ist, dass Sie es mit Base 64 codieren und den Zeichenfolgenwert an loadUrlWithData() übergeben können.

    – Jeffrey Blattmann

    10. September 2012 um 20:10 Uhr

Wie erhalte ich die Zoomfunktion fur Bilder
Digiphd

Als Antwort auf die ursprüngliche Frage von Janusz gibt es mehrere Möglichkeiten, dies zu erreichen, die sich alle in ihrem Schwierigkeitsgrad unterscheiden und unten aufgeführt sind. Die Verwendung einer Webansicht ist gut, aber in Bezug auf Look and Feel und Steuerbarkeit sehr eingeschränkt. Wenn Sie eine Bitmap von einer Leinwand zeichnen, scheinen die vielseitigsten Lösungen, die vorgeschlagen wurden, die von MikeOrtiz, Robert Foss und/oder die von Jacob Nordfalk zu sein. Es gibt ein tolles Beispiel für die Einbindung des Android-Multitouch-Controllers von PaulBourkeund ist großartig für die Multi-Touch-Unterstützung und alle Arten von benutzerdefinierten Ansichten.

Persönlich finde ich die Lösung von MikeOrtiz am einfachsten, wenn Sie einfach eine Leinwand auf eine Bitmap zeichnen und sie dann in ImageView anzeigen und in der Lage sein möchten, mit Multi-Touch hineinzuzoomen und sich zu bewegen. Allerdings ist für meine Zwecke der Code aus der Git das er bereitgestellt hat, scheint nur zu funktionieren, wenn seine benutzerdefinierte ImageView-Klasse TouchImageView das einzige untergeordnete Element ist oder die Layoutparameter wie folgt bereitstellt:

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

Leider brauchte ich aufgrund meines Layoutdesigns “wrap_content” für “layout_height”. Als ich es so änderte, wurde das Bild unten beschnitten und ich konnte nicht in den beschnittenen Bereich scrollen oder zoomen. Also habe ich mir die angeschaut Quelle für ImageView, nur um zu sehen, wie Android “onMeasure” implementiert und MikeOrtiz angepasst hat.

   @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);
}

Hier ist resolveSize(int,int) ein “Dienstprogramm zum Abgleichen einer gewünschten Größe mit Einschränkungen, die durch eine MeasureSpec auferlegt werden, wobei:

Parameter:

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

Kehrt zurück:

 - The size this view should be."

So wird im Wesentlichen ein Verhalten bereitgestellt, das der ursprünglichen ImageView-Klasse etwas ähnlicher ist, wenn das Bild geladen wird. Einige weitere Änderungen könnten vorgenommen werden, um eine größere Vielfalt von Bildschirmen zu unterstützen, die das Seitenverhältnis ändern. Aber im Moment hoffe ich, dass dies hilft. Danke an MikeOrtiz für seinen Originalcode, großartige Arbeit.

Könnte man auch ausprobieren http://code.google.com/p/android-multitouch-controller/

Die Bibliothek ist wirklich toll, wenn auch anfangs etwas schwer zu fassen.

1646645593 387 Wie erhalte ich die Zoomfunktion fur Bilder
zontar

Ich habe gerade TouchImageView von Robert Foss integriert: es funktionierte sofort tadellos! Danke!

Ich habe den Code nur ein wenig geändert, damit ich ihn aus meiner layout.xml instanziieren kann.

Fügen Sie einfach zwei Konstruktoren hinzu

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

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

und transformiere den alten Konstruktor in eine Init-Methode:

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

1646645594 419 Wie erhalte ich die Zoomfunktion fur Bilder
Roman Truba

@Robert Foss, @Mike Ortiz, vielen Dank für Ihre Arbeit. Ich habe Ihre Arbeit zusammengeführt und die Robert-Klassen für Android > 2.0 mit Mikes zusätzlicher Arbeit abgeschlossen.

Als Ergebnis meiner Arbeit präsentiere ich Android Touch Gallery, basierend auf ViewPager und verwendet modifiziertes TouchImageView. Bilder werden per URL geladen und Sie können sie zoomen und ziehen. Sie finden es hier https://github.com/Dreddik/AndroidTouchGallery

964820cookie-checkWie erhalte ich die Zoomfunktion für Bilder?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy