Görüntüler için yakınlaştırma işlevini nasıl alabilirim?


204

Büyük bir görüntü göstermenin ve kullanıcının görüntüyü yakınlaştırıp uzaklaştırıp kaydırmasını sağlamanın yaygın bir yolu var mı?

Şimdiye kadar iki yol buldum:

  1. ImageView'in üzerine yazmak, bu yaygın bir sorun için biraz fazla görünüyor.
  2. bir web görünümü kullanarak, ancak genel düzen üzerinde daha az kontrole sahip olmak vb.

Bir ZOOM CONTROL (Widget) vardır ve kaydırmayı işlemek için OnTouch olayını dinleyebilirsiniz.
tobrien

1
Benzer bir soru stackoverflow.com/questions/2537396/… , bu öğretici ve dev.org/… için bir bağlantı var . Bunu iamge'nizi kaydırmak için yararlı bulabilirsiniz. Ayrıntılı olarak okumadım, ancak yakınlaştırma işlevinin nasıl yapılacağı hakkında da bazı fikirler verebilir.
Steve Haley

Yakınlaştırırken görüntüyü kaydetmeye çalışan var mı? Kaydedilen görüntüyü yakınlaştırılmış durum yerine varsayılan bir durumda istiyorum. Lütfen soruma bakın: stackoverflow.com/questions/24730793/… Teşekkürler
Blaze Tama

Yanıtlar:


208

GÜNCELLEME

TouchImageView'a yeni bir güncelleme verdim. Artık, Kaydırma ve Sıkıştırma Yakınlaştırmasına ek olarak Çift Dokunma Yakınlaştırma ve Fırlatmayı da içerir. Aşağıdaki kod çok tarihli. En son kodu almak için github projesine göz atabilirsiniz .

KULLANIM

Projenize TouchImageView.java yerleştirin. Daha sonra ImageView ile aynı şekilde kullanılabilir. Misal:

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

Xml'de TouchImageView kullanıyorsanız, özel bir görünüm olduğu için tam paket adını sağlamanız gerekir. Misal:

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

Not: Bazı eski kodları içeren önceki cevabımı kaldırdım ve şimdi doğrudan github'daki en güncel koda bağlanıyor.

ViewPager

TouchImageView öğesini bir ViewPager içine koymakla ilgileniyorsanız, bu cevaba bakınız.


4
Paulo, performans sorunları yaşamadım, ancak tablette test yapamadım. Yavaşça, laggy demek istiyorsun? OnScale'in başında 1.05 maksimum zoom faktörü ayarladım. Bahsettiğin bu mu? Değilse, aşağıdakileri deneyin: 1. Hata ayıklama modunda mısınız? Bu onu önemli ölçüde yavaşlatacaktır. 2. Hangi boyutta görüntüler ayarlıyorsunuz. Çok büyük (8mp) görüntülerle test yapmadım, ancak bu yavaşlayabilir. 3. Test edebileceğiniz bir telefonunuz var mı? 4. Her şey başarısız olursa, mScaleFactor ile 2 (> 1 ise) veya 0,5 (<1 ise) ile çarpmanın durumunuza yardımcı olup olmadığına bakın.
Mike Ortiz

3
@Ahsan Görünüm yapıcısını şu şekilde değiştirin: TouchImageView(Context context, AttributeSet attrs)ve çağrı super(context, attrs);Bunun nedeni, özel görünümü şişirdiğinizde , yalnızca bir parametre yerine iki parametre ile yapılandırılmış olmasıdır. Ben bunu almak zaman, ben üç görünüm yapıcıları ve çekilebilir desteklemek için TouchImageView düzeltir.
Mike Ortiz

2
@Ahsan Özel bir görünüm olduğu için, tüm adı XML dosyasına yazmanız gerekir <com.example.TouchImageView android:id="@+id/img" />. Onu yaptınmı?
Mike Ortiz

1
Bu harika şeyler, çağlar boyunca bunu arıyordum. Github'un kodunu daha yeni olduğu ve sadece daha iyi çalıştığı için kullanın
Alex

2
@Mike bu kodu denedim ama özel galeri çalışmıyor. Bu soruna geçici bir çözüm var mı?
Umesh

80

Multitouch (> 2.1) özelliğini destekleyen bir TouchImageView oluşturmak için bazı kodları uyarladım. Esinlenen kitap Merhaba, Android! (3. baskı)

Aşağıdaki 3 dosyada bulunur 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, eğer bu sınır yargıç eklerseniz, daha iyi düşebilir. Kodunuzu çok iyi teşekkür ederim
pengwang

3
İşe yarıyor, ama konuyu anlamıyorum WrapMotionEventve EclairMotionEvent... yine de +1.
Cipi

2
Bunu destekleyen telefonlar için çoklu dokunma. Android için düzenli bir dokunuş <2.0
Robert Foss

Güzel örnek iyi çalışıyor ama i Viewer ne alamadım (Viewer.isDebug == true) {dumpEvent (event); }
Tofeeq Ahmad

2
Bu nedir? >> se.robertfoss.ChanImageBrowser.Viewer
emeraldhieu

60

Bir WebView kullandım ve görüntüyü bellekten

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

WebView tüm kaydırma yakınlaştırma ve kaydırma işlemlerini gerçekleştirir. Wrap_content kullanırsanız, görüntü daha büyük olmaz ve beyaz alanlar gösterilmez. WebView daha iyi ImageView;)


5
Aynı yaklaşımı kullanıyorum. Kullanıcının yakınlaştırma ve kaydırma yapabilmesini istediğim büyük bir metro haritam var. Yine de oldukça büyük bir görüntünüz varsa (yani 1000 veya 3000 piksel genişliğinde), yakınlaştırdığınızda görüntünün bulanıklaştığını fark ettim. Coliris büyük bir yakınlaştırılmış görüntüyü çok keskin görüntüleyemiyor gibi görünüyor. Orijinal görüntü sıkıştırılmamış ve çok keskin olmasına rağmen. Bu yüzden büyük bir resmi daha küçük dilimler halinde kesip tekrar HTML ile bir araya getirdim. Bu şekilde görüntüyü yakınlaştırırken keskin kalır. (Nexus One'da, 2.2 sürümünden önce ve şimdi 2.2
sürümündeyim

@Mathias Lin: tel üzerinden büyük bir görüntü gönderilirse, taşıyıcıların büyük görüntüleri sıkıştırdığını duydum . bu kullanım çantası size uygun mu yoksa resmi yerel olarak yüklediniz mi?
Samuel

@Sam Quest: yerel olarak yükleniyor
Mathias Conradt

4
webview'ın yerleşik zoom düğmelerini kullanmak ve farklı telefonlarda ve gelecekteki android platform sürümlerinde çalışmayabilecek tamamen yeni bir algo yazmaktan çok yakınlaştırmak / uzaklaştırmak için çimdik desteğini kullanmak çok daha iyi
sami

2
bu çözüm yalnızca görüntünün diskte oturması durumunda veya 64 kodlama tabanını oluşturacak ve dize değerini loadUrlWithData () öğesine geçirebileceğiniz kadar küçükse uygulanabilir.
Jeffrey Blattman

7

Janusz'un orijinal sorusuna yanıt olarak, bunların hepsinin zorluk seviyelerine göre değişen ve aşağıda belirtilmiş olan birkaç yolu vardır. Bir web görünümü kullanmak iyidir, ancak görünüm ve his ve kontrol edilebilirlik açısından çok sınırlıdır. Bir tuvalden bir bitmap çiziyorsanız, önerilen en çok yönlü çözümler MikeOrtiz, Robert Foss ve / veya Jacob Nordfalk'ın önerdiği gibi görünüyor. PaulBourke'nin android-multitouch-denetleyicisini dahil etmek için harika bir örnek var ve çoklu dokunmatik desteğe ve özel görünümlerin tüm sahip olmak için harika.

Şahsen, sadece bir tuvali bir bitmap'e çizip sonra onu ve ImageView'i görüntülüyorsanız ve çoklu dokunma kullanarak yakınlaştırıp hareket edebilmek istiyorsanız, MikeOrtiz'in çözümünü en kolay olarak buluyorum. Ancak, benim amacım için onun Git Git kodu sadece onun TouchImageView özel ImageView sınıfı tek çocuk olduğunda veya düzen parametrelerini sağlamak gibi çalışıyor gibi görünüyor:

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

Ne yazık ki benim düzen tasarımı nedeniyle, "layout_height" için "wrap_content" gerekiyordu. Bunu değiştirdiğimde görüntü alttan kırpılmıştı ve kırpılan bölgeye kaydırılamıyor veya zum yapamıyordum. Bu yüzden, Android'in "onMeasure" uygulamasını nasıl uyguladığını ve MikeOrtiz'in uygun olmasını nasıl değiştirdiğini görmek için ImageView Kaynağına baktım.

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

Burada resolSize (int, int), "MeasureSpec tarafından uygulanan kısıtlamalarla istenen bir boyutu uzlaştırmak için bir yardımcı programdır, burada:

Parametreler:

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

İadeler:

 - The size this view should be."

Bu nedenle, aslında görüntü yüklendiğinde orijinal ImageView sınıfına biraz daha benzer bir davranış sağlar. En boy oranını değiştiren çok çeşitli ekranları desteklemek için bazı değişiklikler yapılabilir. Ama şimdilik umarım bu yardımcı olur. MikeOrtiz'e orijinal kodu için teşekkürler, harika çalışmalar.


Bu düzeltme Mike'ın github deposuna dahil edildi mi?
LarsH


6

Robert Foss'un TouchImageView'ı yeni entegre ettim: kutudan mükemmel bir şekilde çalıştı! Teşekkürler!

Sadece layout.xml'den başlatabildiğim için kodu biraz değiştirdim.

Sadece iki kurucu ekleyin

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

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

ve eski kurucuyu bir init yöntemine dönüştürür:

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

3

@Robert Foss, @Mike Ortiz, çalışmanız için çok teşekkür ederim. Çalışmanızı birleştirdim ve Mike> ek çalışmasıyla android> 2.0 için Robert derslerini tamamladım.

Çalışmamın sonucu olarak, ViewPager tabanlı ve modifiye TouchImageView kullanılan Android Touch Gallery'yi sunuyorum. Resimler URL ile yüklenir ve onları yakınlaştırabilir ve sürükleyebilirsiniz. Burada bulabilirsiniz https://github.com/Dreddik/AndroidTouchGallery



2

@ Mike'ın cevabına ekleniyor. Ayrıca, ilk izlendiğinde görüntüyü orijinal boyutlarına geri yüklemek için iki kez hafifçe dokunmam gerekiyordu. Bu yüzden "orig ..." örnek değişkenlerinin bir yığınını ekledim ve hile yapan SimpleOnGestureListener'ı ekledim.

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

Bu iş parçacığına çok geç bir eklentidir, ancak yakınlaştırmayı ve kaydırmayı destekleyen ve başka bir yerde bulamadığım birkaç özelliğe sahip bir görüntü görünümü üzerinde çalışıyorum. Bu, çok büyük görüntüleri neden olmadan görüntülemenin bir yolu olarak OutOfMemoryError, yakınlaştırıldığında görüntüyü alt örnekleyerek ve yakınlaştırıldığında daha yüksek çözünürlüklü karoları yükleyerek başladı. Artık a ViewPager, döndürme veya EXIF ​​bilgilerini (90 ° duraklar) kullanarak, OnClickListenerveya kendinizinkini kullanarak seçilen dokunma olaylarını geçersiz kılma GestureDetectorveyaOnTouchListener alt öğelerinizi bindirme eklemek için alt sınıflandırma, yakınlaştırma sırasında kaydır ve hızlanma.

Genel kullanım amaçlı bir yedek olarak tasarlanmamıştır. ImageView bu nedenle genişletmez ve kaynaklardan, yalnızca varlıklardan ve harici dosyalardan gelen görüntülerin görüntülenmesini desteklemez. SDK 10 gerektirir.

Kaynak GitHub'da ve a ViewPager.

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


1

Bunun için LayoutParams'ı kullanmayı deneyebilirsiniz

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 (doğru); ZoomOut = zoom (yanlış);


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

ve çekilebilir klasör bticn resim dosyasına sahip olmalıdır. mükemmel çalışıyor :)


0

Aşağıdaki gibi bir şey yapacaktır.

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

Tam programı görüntülemek için buraya bakın: Android'de görüntüyü yakınlaştırma programı

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.