web-dev-qa-db-fra.com

Android ImageView Zoom-in et Zoom-Out

Je souhaite effectuer un zoom avant et arrière sur une ImageView Android. J'ai essayé la plupart des exemples, mais dans chacun d'eux, l'image dans ImageView même devient zoomée avant et arrière, alors que je souhaite effectuer un zoom avant et arrière sur ImageView. Je souhaite augmenter la largeur et la hauteur d'ImageView lors d'un zoom avant et réduire la largeur et la hauteur d'Image View pendant un zoom arrière. Comment puis-je y arriver?

92
karthi

Faire deux classes Java

Classe de zoom

import Android.content.Context;
import Android.graphics.Canvas;
import Android.graphics.drawable.Drawable;
import Android.view.KeyEvent;
import Android.view.View;
import Android.widget.Button;
import Android.widget.ImageButton;

public class Zoom extends View {

    private Drawable image;
    ImageButton img,img1;
    private int zoomControler=20;

    public Zoom(Context context){
            super(context);

            image=context.getResources().getDrawable(R.drawable.j);
            //image=context.getResources().getDrawable(R.drawable.icon);

            setFocusable(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //here u can control the width and height of the images........ this line is very important
        image.setBounds((getWidth()/2)-zoomControler, (getHeight()/2)-zoomControler, (getWidth()/2)+zoomControler, (getHeight()/2)+zoomControler);
        image.draw(canvas);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

            if(keyCode==KeyEvent.KEYCODE_DPAD_UP){
                    // zoom in
                    zoomControler+=10;
            }
            if(keyCode==KeyEvent.KEYCODE_DPAD_DOWN){
                    // zoom out
                    zoomControler-=10;
            }
            if(zoomControler<10){
                    zoomControler=10;
            }

            invalidate();
            return true;
    }
}

faire en deuxième classe

import Android.app.Activity;
import Android.os.Bundle;

public class Zoomexample extends Activity {
   /** Called when the activity is first created. */

   @Override
   public void onCreate(Bundle icicle) {
       super.onCreate(icicle);
       setContentView(new Zoom(this));
   }
}
26
Amandeep singh

Suivez la classe ci-dessous, utilisée pour les zooms avant et arrière pour ImageView.

import Android.app.Activity;
import Android.graphics.Matrix;
import Android.graphics.PointF;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.MotionEvent;
import Android.view.View;
import Android.view.View.OnTouchListener;
import Android.widget.ImageView;

public class ZoomInZoomOut extends Activity implements OnTouchListener 
{
    private static final String TAG = "Touch";
    @SuppressWarnings("unused")
    private static final float MIN_ZOOM = 1f,MAX_ZOOM = 1f;

    // These matrices will be used to scale points of the image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();

    // The 3 states (events) which the user is trying to perform
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;

    // these PointF objects are used to record the point(s) the user is touching
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ImageView view = (ImageView) findViewById(R.id.imageView);
        view.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) 
    {
        ImageView view = (ImageView) v;
        view.setScaleType(ImageView.ScaleType.MATRIX);
        float scale;

        dumpEvent(event);
        // Handle touch events here...

        switch (event.getAction() & MotionEvent.ACTION_MASK) 
        {
            case MotionEvent.ACTION_DOWN:   // first finger down only
                                                savedMatrix.set(matrix);
                                                start.set(event.getX(), event.getY());
                                                Log.d(TAG, "mode=DRAG"); // write to LogCat
                                                mode = DRAG;
                                                break;

            case MotionEvent.ACTION_UP: // first finger lifted

            case MotionEvent.ACTION_POINTER_UP: // second finger lifted

                                                mode = NONE;
                                                Log.d(TAG, "mode=NONE");
                                                break;

            case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down

                                                oldDist = spacing(event);
                                                Log.d(TAG, "oldDist=" + oldDist);
                                                if (oldDist > 5f) {
                                                    savedMatrix.set(matrix);
                                                    midPoint(mid, event);
                                                    mode = ZOOM;
                                                    Log.d(TAG, "mode=ZOOM");
                                                }
                                                break;

            case MotionEvent.ACTION_MOVE:

                                                if (mode == DRAG) 
                                                { 
                                                    matrix.set(savedMatrix);
                                                    matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix  of points
                                                } 
                                                else if (mode == ZOOM) 
                                                { 
                                                    // pinch zooming
                                                    float newDist = spacing(event);
                                                    Log.d(TAG, "newDist=" + newDist);
                                                    if (newDist > 5f) 
                                                    {
                                                        matrix.set(savedMatrix);
                                                        scale = newDist / oldDist; // setting the scaling of the
                                                                                    // matrix...if scale > 1 means
                                                                                    // zoom in...if scale < 1 means
                                                                                    // zoom out
                                                        matrix.postScale(scale, scale, mid.x, mid.y);
                                                    }
                                                }
                                                break;
        }

        view.setImageMatrix(matrix); // display the transformation on screen

        return true; // indicate event was handled
    }

    /*
     * --------------------------------------------------------------------------
     * Method: spacing Parameters: MotionEvent Returns: float Description:
     * checks the spacing between the two fingers on touch
     * ----------------------------------------------------
     */

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

    /*
     * --------------------------------------------------------------------------
     * Method: midPoint Parameters: PointF object, MotionEvent Returns: void
     * Description: calculates the midpoint between the two fingers
     * ------------------------------------------------------------
     */

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

    /** Show an event in the LogCat view, for debugging */
    private void dumpEvent(MotionEvent 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("Touch Events ---------", sb.toString());
    }
}
185
Chirag

Les autres implémentations ici ont toutes une sorte de défaut. donc je les ai fondamentalement mélangés et j'ai trouvé ça.

Créez une vue personnalisée comme celle-ci:

ZoomableImageView.Java:

import Android.content.Context;
import Android.graphics.Bitmap;
import Android.graphics.Matrix;
import Android.graphics.PointF;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.view.ScaleGestureDetector;
import Android.view.View;
import Android.widget.ImageView;

public class ZoomableImageView extends ImageView
{
    Matrix matrix = new Matrix();

    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    static final int CLICK = 3;
    int mode = NONE;

    PointF last = new PointF();
    PointF start = new PointF();
    float minScale = 1f;
    float maxScale = 4f;
    float[] m;

    float redundantXSpace, redundantYSpace;
    float width, height;
    float saveScale = 1f;
    float right, bottom, origWidth, origHeight, bmWidth, bmHeight;

    ScaleGestureDetector mScaleDetector;
    Context context;

    public ZoomableImageView(Context context, AttributeSet attr)
    {
        super(context, attr);
        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())
                {
                    //when one finger is touching
                    //set the mode to DRAG
                    case MotionEvent.ACTION_DOWN:
                        last.set(event.getX(), event.getY());
                        start.set(last);
                        mode = DRAG;
                        break;
                    //when two fingers are touching
                    //set the mode to ZOOM
                    case MotionEvent.ACTION_POINTER_DOWN:
                        last.set(event.getX(), event.getY());
                        start.set(last);
                        mode = ZOOM;
                        break;
                    //when a finger moves
                    //If mode is applicable move image
                    case MotionEvent.ACTION_MOVE:
                        //if the mode is ZOOM or
                        //if the mode is DRAG and already zoomed
                        if (mode == ZOOM || (mode == DRAG && saveScale > minScale))
                        {
                            float deltaX = curr.x - last.x;// x difference
                            float deltaY = curr.y - last.y;// y difference
                            float scaleWidth = Math.round(origWidth * saveScale);// width after applying current scale
                            float scaleHeight = Math.round(origHeight * saveScale);// height after applying current scale
                            //if scaleWidth is smaller than the views width
                            //in other words if the image width fits in the view
                            //limit left and right movement
                            if (scaleWidth < width)
                            {
                                deltaX = 0;
                                if (y + deltaY > 0)
                                    deltaY = -y;
                                else if (y + deltaY < -bottom)
                                    deltaY = -(y + bottom);
                            }
                            //if scaleHeight is smaller than the views height
                            //in other words if the image height fits in the view
                            //limit up and down movement
                            else if (scaleHeight < height)
                            {
                                deltaY = 0;
                                if (x + deltaX > 0)
                                    deltaX = -x;
                                else if (x + deltaX < -right)
                                    deltaX = -(x + right);
                            }
                            //if the image doesnt fit in the width or height
                            //limit both up and down and left and 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);
                            }
                            //move the image with the matrix
                            matrix.postTranslate(deltaX, deltaY);
                            //set the last touch location to the current
                            last.set(curr.x, curr.y);
                        }
                        break;
                    //first finger is lifted
                    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;
                    // second finger is lifted
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        break;
                }
                setImageMatrix(matrix);
                invalidate();
                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 = detector.getScaleFactor();
            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 =  width / bmWidth;
        float scaleY = height / bmHeight;
        scale = Math.min(scaleX, scaleY);
        matrix.setScale(scale, scale);
        setImageMatrix(matrix);
        saveScale = 1f;

        // Center the image
        redundantYSpace = height - (scale * bmHeight) ;
        redundantXSpace = width - (scale * bmWidth);
        redundantYSpace /= 2;
        redundantXSpace /= 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);
    }
}

Ajoutez ensuite l'image comme ceci:

ZoomableImageView touch = (ZoomableImageView)findViewById(R.id.IMAGEID);
touch.setImageBitmap(bitmap);

Ajoutez la vue comme ceci en XML:

<PACKAGE.ZoomableImageView
Android:id="@+id/IMAGEID"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
89
Nicolas Tyler

Manière simple:

PhotoViewAttacher pAttacher;
pAttacher = new PhotoViewAttacher(Your_Image_View);
pAttacher.update();

Ajouter la ligne ci-dessous dans build.gradle

compile 'com.commit451:PhotoView:1.2.4'
19

utilisez simplement cette classe: TouchImageView

13
Anjula

C'est encore une autre implémentation basée sur le code posté par Nicolas Tyler.

Les bugs suivants sont corrigés:

  • Définir minScale à un nombre inférieur à 1 fonctionne désormais
  • Vous n'avez pas besoin d'utiliser setImageBitmap() pour définir l'image (vous pouvez utiliser, par exemple, setImageResource()
  • Tous les constructeurs fonctionnent maintenant correctement

Les choses suivantes, entre autres, sont rangées:

  • Un OnTouchListener n'est pas utilisé, ce n'est pas nécessaire car la classe peut simplement implémenter la méthode onTouchEvent().

  • L'affectation right = width * saveScale - width - (2 * redundantXSpace * saveScale); a été simplifiée à right = (originalBitmapWidth * saveScale) - width, ce qui, dans mon cas, est beaucoup moins déroutant.

  • Certaines variables membres sont supprimées (plusieurs états peuvent probablement être supprimés de cette classe)

Ce n'est pas parfait mais c'est parti:

import Android.content.Context;
import Android.graphics.Matrix;
import Android.graphics.PointF;
import Android.graphics.drawable.Drawable;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.view.ScaleGestureDetector;
import Android.widget.ImageView;

/**
 * Created by alex on 23/02/16.
 * Based on code posted by Nicolas Tyler here:
 * https://stackoverflow.com/questions/6650398/Android-imageview-zoom-in-and-zoom-out
 */
public class ZoomableImageView extends ImageView {

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            mode = ZOOM;
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float scaleFactor = detector.getScaleFactor();
            float newScale = saveScale * scaleFactor;
            if (newScale < maxScale && newScale > minScale) {
                saveScale = newScale;
                float width = getWidth();
                float height = getHeight();
                right = (originalBitmapWidth * saveScale) - width;
                bottom = (originalBitmapHeight * saveScale) - height;

                float scaledBitmapWidth = originalBitmapWidth * saveScale;
                float scaledBitmapHeight = originalBitmapHeight * saveScale;

                if (scaledBitmapWidth <= width || scaledBitmapHeight <= height) {
                    matrix.postScale(scaleFactor, scaleFactor, width / 2, height / 2);
                } else {
                    matrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
                }
            }
            return true;
        }

    }

    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    static final int CLICK = 3;

    private int mode = NONE;

    private Matrix matrix = new Matrix();

    private PointF last = new PointF();
    private PointF start = new PointF();
    private float minScale = 0.5f;
    private float maxScale = 4f;
    private float[] m;

    private float redundantXSpace, redundantYSpace;
    private float saveScale = 1f;
    private float right, bottom, originalBitmapWidth, originalBitmapHeight;

    private ScaleGestureDetector mScaleDetector;

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

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

    public ZoomableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        super.setClickable(true);
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        m = new float[9];
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int bmHeight = getBmHeight();
        int bmWidth = getBmWidth();

        float width = getMeasuredWidth();
        float height = getMeasuredHeight();
        //Fit to screen.
        float scale = width > height ? height / bmHeight :  width / bmWidth;

        matrix.setScale(scale, scale);
        saveScale = 1f;

        originalBitmapWidth = scale * bmWidth;
        originalBitmapHeight = scale * bmHeight;

        // Center the image
        redundantYSpace = (height - originalBitmapHeight);
        redundantXSpace = (width - originalBitmapWidth);

        matrix.postTranslate(redundantXSpace / 2, redundantYSpace / 2);

        setImageMatrix(matrix);
    }

    @Override
    public boolean onTouchEvent(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()) {
            //when one finger is touching
            //set the mode to DRAG
            case MotionEvent.ACTION_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = DRAG;
                break;
            //when two fingers are touching
            //set the mode to ZOOM
            case MotionEvent.ACTION_POINTER_DOWN:
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = ZOOM;
                break;
            //when a finger moves
            //If mode is applicable move image
            case MotionEvent.ACTION_MOVE:
                //if the mode is ZOOM or
                //if the mode is DRAG and already zoomed
                if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
                    float deltaX = curr.x - last.x;// x difference
                    float deltaY = curr.y - last.y;// y difference
                    float scaleWidth = Math.round(originalBitmapWidth * saveScale);// width after applying current scale
                    float scaleHeight = Math.round(originalBitmapHeight * saveScale);// height after applying current scale

                    boolean limitX = false;
                    boolean limitY = false;

                    //if scaleWidth is smaller than the views width
                    //in other words if the image width fits in the view
                    //limit left and right movement
                    if (scaleWidth < getWidth() && scaleHeight < getHeight()) {
                        // don't do anything
                    }
                    else if (scaleWidth < getWidth()) {
                        deltaX = 0;
                        limitY = true;
                    }
                    //if scaleHeight is smaller than the views height
                    //in other words if the image height fits in the view
                    //limit up and down movement
                    else if (scaleHeight < getHeight()) {
                        deltaY = 0;
                        limitX = true;
                    }
                    //if the image doesnt fit in the width or height
                    //limit both up and down and left and right
                    else {
                        limitX = true;
                        limitY = true;
                    }

                    if (limitY) {
                        if (y + deltaY > 0) {
                            deltaY = -y;
                        } else  if (y + deltaY < -bottom) {
                            deltaY = -(y + bottom);
                        }

                    }

                    if (limitX) {
                        if (x + deltaX > 0) {
                            deltaX = -x;
                        } else if (x + deltaX < -right) {
                            deltaX = -(x + right);
                        }

                    }
                    //move the image with the matrix
                    matrix.postTranslate(deltaX, deltaY);
                    //set the last touch location to the current
                    last.set(curr.x, curr.y);
                }
                break;
            //first finger is lifted
            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;
            // second finger is lifted
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
        }
        setImageMatrix(matrix);
        invalidate();
        return true;
    }

    public void setMaxZoom(float x) {
        maxScale = x;
    }

    private int getBmWidth() {
        Drawable drawable = getDrawable();
        if (drawable != null) {
            return drawable.getIntrinsicWidth();
        }
        return 0;
    }

    private int getBmHeight() {
        Drawable drawable = getDrawable();
        if (drawable != null) {
            return drawable.getIntrinsicHeight();
        }
        return 0;
    }
}
10
alexbirkett

J'ai créé ma propre image view personnalisée avec pincement pour zoomer. Il n'y a pas de limites/frontières sur le code Chirag Raval s, ainsi l'utilisateur peut faire glisser l'image hors de l'écran. 

Voici la classe CustomImageView:

    public class CustomImageVIew extends ImageView implements OnTouchListener {


    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();

    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;

    private int mode = NONE;

    private PointF mStartPoint = new PointF();
    private PointF mMiddlePoint = new PointF();
    private Point mBitmapMiddlePoint = new Point();

    private float oldDist = 1f;
    private float matrixValues[] = {0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f};
    private float scale;
    private float oldEventX = 0;
    private float oldEventY = 0;
    private float oldStartPointX = 0;
    private float oldStartPointY = 0;
    private int mViewWidth = -1;
    private int mViewHeight = -1;
    private int mBitmapWidth = -1;
    private int mBitmapHeight = -1;
    private boolean mDraggable = false;


    public CustomImageVIew(Context context) {
        this(context, null, 0);
    }

    public CustomImageVIew(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomImageVIew(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setOnTouchListener(this);
    }

    @Override
    public void onSizeChanged (int w, int h, int oldw, int oldh){
        super.onSizeChanged(w, h, oldw, oldh);
        mViewWidth = w;
        mViewHeight = h;
    }

    public void setBitmap(Bitmap bitmap){
        if(bitmap != null){
            setImageBitmap(bitmap);

            mBitmapWidth = bitmap.getWidth();
            mBitmapHeight = bitmap.getHeight();
            mBitmapMiddlePoint.x = (mViewWidth / 2) - (mBitmapWidth /  2);
            mBitmapMiddlePoint.y = (mViewHeight / 2) - (mBitmapHeight / 2);

            matrix.postTranslate(mBitmapMiddlePoint.x, mBitmapMiddlePoint.y);
            this.setImageMatrix(matrix);
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event){
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            savedMatrix.set(matrix);
            mStartPoint.set(event.getX(), event.getY());
            mode = DRAG;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            if(oldDist > 10f){
                savedMatrix.set(matrix);
                midPoint(mMiddlePoint, event);
                mode = ZOOM;
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
        case MotionEvent.ACTION_MOVE:
            if(mode == DRAG){
                drag(event);
            } else if(mode == ZOOM){
                zoom(event);
            } 
            break;
        }

        return true;
    }



   public void drag(MotionEvent event){
       matrix.getValues(matrixValues);

       float left = matrixValues[2];
       float top = matrixValues[5];
       float bottom = (top + (matrixValues[0] * mBitmapHeight)) - mViewHeight;
       float right = (left + (matrixValues[0] * mBitmapWidth)) -mViewWidth;

       float eventX = event.getX();
       float eventY = event.getY();
       float spacingX = eventX - mStartPoint.x;
       float spacingY = eventY - mStartPoint.y;
       float newPositionLeft = (left  < 0 ? spacingX : spacingX * -1) + left;
       float newPositionRight = (spacingX) + right;
       float newPositionTop = (top  < 0 ? spacingY : spacingY * -1) + top;
       float newPositionBottom = (spacingY) + bottom;
       boolean x = true;
       boolean y = true;

       if(newPositionRight < 0.0f || newPositionLeft > 0.0f){
           if(newPositionRight < 0.0f && newPositionLeft > 0.0f){
               x = false;
           } else{
               eventX = oldEventX;
               mStartPoint.x = oldStartPointX;
           }
       }
       if(newPositionBottom < 0.0f || newPositionTop > 0.0f){
           if(newPositionBottom < 0.0f && newPositionTop > 0.0f){
               y = false;
           } else{
               eventY = oldEventY;
               mStartPoint.y = oldStartPointY;
           }
       }

       if(mDraggable){
           matrix.set(savedMatrix);
           matrix.postTranslate(x? eventX - mStartPoint.x : 0, y? eventY - mStartPoint.y : 0);
           this.setImageMatrix(matrix);
           if(x)oldEventX = eventX;
           if(y)oldEventY = eventY;
           if(x)oldStartPointX = mStartPoint.x;
           if(y)oldStartPointY = mStartPoint.y;
       }

   }

   public void zoom(MotionEvent event){
       matrix.getValues(matrixValues);

       float newDist = spacing(event);
       float bitmapWidth = matrixValues[0] * mBitmapWidth;
       float bimtapHeight = matrixValues[0] * mBitmapHeight;
       boolean in = newDist > oldDist;

       if(!in && matrixValues[0] < 1){
           return;
       }
       if(bitmapWidth > mViewWidth || bimtapHeight > mViewHeight){
           mDraggable = true;
       } else{
           mDraggable = false;
       }

       float midX = (mViewWidth / 2);
       float midY = (mViewHeight / 2);

       matrix.set(savedMatrix);
       scale = newDist / oldDist;
       matrix.postScale(scale, scale, bitmapWidth > mViewWidth ? mMiddlePoint.x : midX, bimtapHeight > mViewHeight ? mMiddlePoint.y : midY); 

       this.setImageMatrix(matrix);


   }





    /** Determine the space between the first two fingers */
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);

        return (float)Math.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    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);
    }


}

Voici comment vous pouvez l'utiliser dans votre activité:

CustomImageVIew mImageView = (CustomImageVIew)findViewById(R.id.customImageVIew1);
mImage.setBitmap(your bitmap);

Et mise en page:

<your.package.name.CustomImageVIew
        Android:id="@+id/customImageVIew1"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        Android:layout_marginBottom="15dp"
        Android:layout_marginLeft="15dp"
        Android:layout_marginRight="15dp"
        Android:layout_marginTop="15dp"
        Android:layout_centerHorizontal="true"
        Android:layout_centerVertical="true" 
        Android:scaleType="matrix"/> // important
6
user1888162

Je pense que la réponse de Chirag Ravals est excellente!

La seule chose qui pourrait être améliorée est de déplacer tout ce code dans une classe comme: 

PinchZoomImageView extends ImageView {...

et en y ajoutant l'initialisation initiale de la matrice d'image pour empêcher le zoom après le premier tap:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    matrix = new Matrix(this.getImageMatrix());
}

BTW, cela corrigera un bug mentionné par Muhammad Umar et Baz

P.S. Il peut également être utile de disposer de limites de zoom maximales et minimales . E.g Le zoom maximal est égal à 2X et le zoom minimal correspond à la taille d'origine lorsque l'image est adaptée à l'écran:

static final int MAX_SCALE_FACTOR = 2;

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

    // Getting initial Image matrix
    mViewMatrix = new Matrix(this.getImageMatrix());
    mMinScaleMatrix = new Matrix(mViewMatrix);
    float initialScale = getMatrixScale(mViewMatrix);


    if (initialScale < 1.0f) // Image is bigger than screen
        mMaxScale = MAX_SCALE_FACTOR;
    else
        mMaxScale = MAX_SCALE_FACTOR * initialScale;

    mMinScale = getMatrixScale(mMinScaleMatrix);
}


@Override
public boolean onTouch(View v, MotionEvent event) {
    ImageView view = (ImageView) v;
    // We set scale only after onMeasure was called and automatically fit image to screen
    if(!mWasScaleTypeSet) {
        view.setScaleType(ImageView.ScaleType.MATRIX);
        mWasScaleTypeSet = true;
    }

    float scale;

    dumpEvent(event);

    switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: // first finger down only
        mCurSavedMatrix.set(mViewMatrix);
        start.set(event.getX(), event.getY());
        mCurrentMode = DRAG;
        break;

    case MotionEvent.ACTION_UP: // first finger lifted
    case MotionEvent.ACTION_POINTER_UP: // second finger lifted
        mCurrentMode = NONE;

        float resScale = getMatrixScale(mViewMatrix);

        if (resScale > mMaxScale) {
            downscaleMatrix(resScale, mViewMatrix);
        } else if (resScale < mMinScale)
            mViewMatrix = new Matrix(mMinScaleMatrix);
        else if ((resScale - mMinScale) < 0.1f) // Don't allow user to drag picture outside in case of FIT TO WINDOW zoom
            mViewMatrix = new Matrix(mMinScaleMatrix);
        else
            break;

        break;

    case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
        mOldDist = spacing(event);
        Helper.LOGD(TAG, "oldDist=" + mOldDist);
        if (mOldDist > 5f) {
            mCurSavedMatrix.set(mViewMatrix);
            midPoint(mCurMidPoint, event);
            mCurrentMode = ZOOM;
            Helper.LOGD(TAG, "mode=ZOOM");
        }
        break;

    case MotionEvent.ACTION_MOVE:
        if (mCurrentMode == DRAG) {
            mViewMatrix.set(mCurSavedMatrix);
            mViewMatrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix  of points
        } else if (mCurrentMode == ZOOM) {
            // pinch zooming
            float newDist = spacing(event);
            Helper.LOGD(TAG, "newDist=" + newDist);
            if (newDist > 1.f) {
                mViewMatrix.set(mCurSavedMatrix);
                scale = newDist / mOldDist; // setting the scaling of the
                                            // matrix...if scale > 1 means
                                            // zoom in...if scale < 1 means
                                            // zoom out
                mViewMatrix.postScale(scale, scale, mCurMidPoint.x, mCurMidPoint.y);
            }
        }
        break;
    }

    view.setImageMatrix(mViewMatrix); // display the transformation on screen

    return true; // indicate event was handled
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// PRIVATE SECTION ///////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// These matrices will be used to scale points of the image
private Matrix mViewMatrix = new Matrix();
private Matrix mCurSavedMatrix = new Matrix();
// These PointF objects are used to record the point(s) the user is touching
private PointF start = new PointF();
private PointF mCurMidPoint = new PointF();
private float mOldDist = 1f;

private Matrix mMinScaleMatrix;
private float mMinScale;
private float mMaxScale;
float[] mTmpValues = new float[9];
private boolean mWasScaleTypeSet;


/**
 * Returns scale factor of the Matrix
 * @param matrix
 * @return
 */
private float getMatrixScale(Matrix matrix) {
    matrix.getValues(mTmpValues);
    return mTmpValues[Matrix.MSCALE_X];
}

/**
 * Downscales matrix with the scale to maximum allowed scale factor, but the same translations
 * @param scale
 * @param dist
 */
private void downscaleMatrix(float scale, Matrix dist) {
    float resScale = mMaxScale / scale;
    dist.postScale(resScale, resScale, mCurMidPoint.x, mCurMidPoint.y);
}
6
goRGon

Ce code fonctionne et met en œuvre le double tap pour revenir à la taille originale de l'image.

1ère étape - Dans votre mise en page XML, mettez ceci:

<com.****.*****.TouchImageView
    Android:id="@+id/action_infolinks_splash"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:src="@mipmap/myinfolinks_splash"
    Android:layout_gravity="center"
    Android:gravity="center"
    Android:scaleType="fitCenter"
    Android:contentDescription="@string/aboutSupport_description_image"/>

2ème étape - Créer un fichier (TouchImageView.Java) avec la classe TouchImageView:

import Android.content.Context;
import Android.graphics.Bitmap;
import Android.graphics.BitmapFactory;
import Android.graphics.Matrix;
import Android.graphics.PointF;
import Android.util.AttributeSet;
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;

    // 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;

    int viewWidth, viewHeight;
    static final int CLICK = 3;
    static final float SAVE_SCALE = 1f;
    float saveScale = SAVE_SCALE;
    protected float origWidth, origHeight;
    int oldMeasuredWidth, oldMeasuredHeight;
    float origScale, bottom, origBottom, right, origRight;

    ScaleGestureDetector mScaleDetector;
    GestureDetector mGestureDetector;

    Context context;

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

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

    private void sharedConstructing(Context context) {
        super.setClickable(true);
        this.context = context;
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        matrix = new Matrix();
        m = new float[9];
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(new OnTouchListener() {

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

                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);
                PointF curr = new PointF(event.getX(), event.getY());

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        last.set(curr);
                        start.set(last);
                        mode = DRAG;
                        break;

                    case MotionEvent.ACTION_MOVE:
                        if (mode == DRAG) {
                            float deltaX = curr.x - last.x;
                            float deltaY = curr.y - last.y;
                            float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
                            float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);
                            matrix.postTranslate(fixTransX, fixTransY);
                            fixTrans();
                            last.set(curr.x, curr.y);
                        }
                        break;

                    case MotionEvent.ACTION_UP:
                        mode = NONE;
                        int xDiff = (int) Math.abs(curr.x - start.x);
                        int yDiff = (int) Math.abs(curr.y - start.y);
                        if (xDiff < CLICK && yDiff < CLICK) performClick();
                        break;

                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        break;
                }

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

        });

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

    public void setMaxZoom(float x) {
        maxScale = x;
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            mode = ZOOM;
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float mScaleFactor = detector.getScaleFactor();
            //float 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 = viewWidth * saveScale - viewWidth - (2 * redundantXSpace * saveScale);
            bottom = viewHeight * saveScale - viewHeight - (2 * redundantYSpace * saveScale);

            if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
                matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
            else
                matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());

            fixTrans();
            return true;
        }
    }

    void fixTrans() {
        matrix.getValues(m);
        float transX = m[Matrix.MTRANS_X];
        float transY = m[Matrix.MTRANS_Y];

        float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
        float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);

        if (fixTransX != 0 || fixTransY != 0)
            matrix.postTranslate(fixTransX, fixTransY);
    }

    float getFixTrans(float trans, float viewSize, float contentSize) {
        float minTrans, maxTrans;

        if (contentSize <= viewSize) {
            minTrans = 0;
            maxTrans = viewSize - contentSize;
        } else {
            minTrans = viewSize - contentSize;
            maxTrans = 0;
        }

        if (trans < minTrans)
            return -trans + minTrans;
        if (trans > maxTrans)
            return -trans + maxTrans;
        return 0;
    }

    float getFixDragTrans(float delta, float viewSize, float contentSize) {
        if (contentSize <= viewSize) {
            return 0;
        }
        return delta;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewWidth = MeasureSpec.getSize(widthMeasureSpec);
        viewHeight = MeasureSpec.getSize(heightMeasureSpec);

        //
        // Rescales image on rotation
        //
        if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight || viewWidth == 0 || viewHeight == 0) return;

        oldMeasuredHeight = viewHeight;
        oldMeasuredWidth = viewWidth;

        if (saveScale == 1) {
            // Fit to screen.
            float scale;
            int bmWidth,bmHeight;

            Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.mipmap.myinfolinks_splash);
            bmWidth = bm.getWidth();
            bmHeight = bm.getHeight();

            int  w = bmWidth;
            int  h = bmHeight;
            viewWidth = resolveSize(w, widthMeasureSpec);
            viewHeight = resolveSize(h, heightMeasureSpec);

            float scaleX = (float) viewWidth / (float) bmWidth;
            float scaleY = (float) viewHeight / (float) bmHeight;
            scale = Math.min(scaleX, scaleY);
            matrix.setScale(scale, scale);
            saveScale = SAVE_SCALE;
            origScale = scale;

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

            origRedundantXSpace = redundantXSpace;
            origRedundantYSpace = redundantYSpace;

            matrix.postTranslate(redundantXSpace, redundantYSpace);

            origWidth = viewWidth - 2 * redundantXSpace;
            origHeight = viewHeight - 2 * redundantYSpace;

            right = viewWidth * saveScale - viewWidth - (2 * redundantXSpace * saveScale);
            bottom = viewHeight * saveScale - viewHeight - (2 * redundantYSpace * saveScale);
            origRight = right;
            origBottom = bottom;

            setImageMatrix(matrix);
        }
        fixTrans();
    }
}

Et enfin, appelez dans votre activité principale:

TouchImageView imgDisplay = (TouchImageView) messageView.findViewById(R.id.id_myImage);
imgDisplay.setMaxZoom(2f);
imgDisplay.setImageResource(R.drawable.myImage);

J'ai vu beaucoup de code et après mes ajustements, ça marche. Prendre plaisir!

6
jmtsilva69

J'ai amélioré la réponse obtenue de stack pour _ sans défaut ZOOM (deux doigts)/ROTATION (deux doigts)/DRAG (un seul doigt).

 enter image description here

// ============================ Code XML =================

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.example.flochat.imageviewzoomforstack.MainActivity">

    <ImageView
        Android:id="@+id/imageview_trash"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:src="@drawable/trash" />

</LinearLayout>

// =========================== Java code ================= ========

public class MainActivity extends AppCompatActivity {

    ImageView photoview2;
    float[] lastEvent = null;
    float d = 0f;
    float newRot = 0f;
    private boolean isZoomAndRotate;
    private boolean isOutSide;
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    private PointF start = new PointF();
    private PointF mid = new PointF();
    float oldDist = 1f;
    private float xCoOrdinate, yCoOrdinate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_main);

        photoview2 = findViewById(R.id.imageview_trash);

        photoview2.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ImageView view = (ImageView) v;
                view.bringToFront();
                viewTransformation(view, event);
                return true;
            }
        });
    }


    private void viewTransformation(View view, MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
            xCoOrdinate = view.getX() - event.getRawX();
            yCoOrdinate = view.getY() - event.getRawY();

                start.set(event.getX(), event.getY());
                isOutSide = false;
                mode = DRAG;
                lastEvent = null;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                if (oldDist > 10f) {
                    midPoint(mid, event);
                    mode = ZOOM;
                }

                lastEvent = new float[4];
                lastEvent[0] = event.getX(0);
                lastEvent[1] = event.getX(1);
                lastEvent[2] = event.getY(0);
                lastEvent[3] = event.getY(1);
                d = rotation(event);
                break;
            case MotionEvent.ACTION_UP:
                isZoomAndRotate = false;
                if (mode == DRAG) {
                    float x = event.getX();
                    float y = event.getY();
                }
            case MotionEvent.ACTION_OUTSIDE:
                isOutSide = true;
                mode = NONE;
                lastEvent = null;
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                lastEvent = null;
                break;
            case MotionEvent.ACTION_MOVE:
                if (!isOutSide) {
                    if (mode == DRAG) {
                        isZoomAndRotate = false;
                        view.animate().x(event.getRawX() + xCoOrdinate).y(event.getRawY() + yCoOrdinate).setDuration(0).start();
                    }
                    if (mode == ZOOM && event.getPointerCount() == 2) {
                        float newDist1 = spacing(event);
                        if (newDist1 > 10f) {
                            float scale = newDist1 / oldDist * view.getScaleX();
                            view.setScaleX(scale);
                            view.setScaleY(scale);
                        }
                        if (lastEvent != null) {
                            newRot = rotation(event);
                            view.setRotation((float) (view.getRotation() + (newRot - d)));
                        }
                    }
                }
                break;
        }
    }

    private float rotation(MotionEvent event) {
        double delta_x = (event.getX(0) - event.getX(1));
        double delta_y = (event.getY(0) - event.getY(1));
        double radians = Math.atan2(delta_y, delta_x);
        return (float) Math.toDegrees(radians);
    }

    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (int) Math.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);
    }

}

// ======================== Passez simplement la vue que vous souhaitez agrandir/faire pivoter/faire glisser pour afficher la méthode viewTransformation (). Très applicable pour zoom de texte. Cela ne pixellisera pas le texte.

5
Aman Srii

Vous devriez mettre l'image dans la vue Web et travailler avec cela. Les commandes de zoom avant/arrière sont disponibles dans la vue Web.

4
Alfie

J'avais besoin de quelque chose de similaire, mais j'avais besoin de pouvoir obtenir facilement les dimensions et aussi glisser-déposer. Je me suis basé sur la réponse donnée par Nicolas Tyler et l’a modifiée à partir de là. 

Les fonctions sont un zoom avant/arrière pincé, une pression longue sur la vibration/glisser/déposer en surbrillance. 

Pour l'utiliser, ajoutez cette classe CustomZoomView à votre projet.

public class CustomZoomView extends View implements View.OnTouchListener, View.OnLongClickListener{


private Paint mPaint;

Vibrator v;

static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
static final int MOVE = 3;

private int mode = NONE;

Rect src;
Rect mTempDst = new Rect();
Rect dst = new Rect();

Bitmap mBitmap;

private int mBitmapWidth = -1;
private int mBitmapHeight = -1;

private PointF mStartPoint = new PointF();
private PointF mMiddlePoint = new PointF();
private PointF mStartDragPoint = new PointF();
private PointF mMovePoint = new PointF();

private float oldDist = 1f;
private float scale;
private float oldEventX = 0;
private float oldEventY = 0;
private float oldStartPointX = 0;
private float oldStartPointY = 0;
private int mViewWidth = -1;
private int mViewHeight = -1;

private boolean mDraggable = false;


public CustomZoomView(Context context) {
    this(context, null, 0);

}

public CustomZoomView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public CustomZoomView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.setOnTouchListener(this);
    this.setOnLongClickListener(this);
    v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    mPaint = new Paint();
    mPaint.setColorFilter(new PorterDuffColorFilter(Color.argb(100,255,255,255), PorterDuff.Mode.SRC_IN));
}

@Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mViewWidth = w;
    mViewHeight = h;
}

public void setBitmap(Bitmap bitmap) {
    if (bitmap != null) {

        src = new Rect();
        src.left = 0;
        src.top = 0;
        src.right = bitmap.getWidth();
        src.bottom = bitmap.getHeight();
        mBitmap = bitmap;

        mBitmapWidth = bitmap.getWidth() * 1;
        mBitmapHeight = bitmap.getHeight() * 1;

        dst = new Rect();
        dst.left = (mViewWidth / 2) - (mBitmapWidth / 2);
        dst.top = (mViewHeight / 2) - (mBitmapHeight / 2);
        dst.right = (mViewWidth / 2) + (mBitmapWidth / 2);
        dst.bottom = (mViewHeight / 2) + (mBitmapHeight / 2);

    }
}


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

    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            mStartPoint.set(event.getX(), event.getY());
            mStartDragPoint.set(event.getX(), event.getY());
            mTempDst.set(dst.left, dst.top, dst.right, dst.bottom);
            mode = DRAG;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            if (oldDist > 10f) {
                midPoint(mMiddlePoint, event);
                mode = ZOOM;
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            if (mode == ZOOM) {
                mBitmapWidth = dst.right - dst.left;
                mBitmapHeight = dst.bottom - dst.top;
            }
            mode = NONE;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                mMovePoint.x = event.getX();
                mMovePoint.y = event.getY();
                drag(event);
            } else if (mode == ZOOM) {
                zoom(event);
            } else if (mode == MOVE) {
                move(event);
            }
            break;
    }

    return false;
}

public void move(MotionEvent event) {

    int xChange = (int) (event.getX() - mStartPoint.x);
    int yChange = (int) (event.getY() - mStartPoint.y);

    dst.left = mTempDst.left + (xChange);
    dst.top = mTempDst.top + (yChange);

    dst.right = mTempDst.right + (xChange);
    dst.bottom = mTempDst.bottom + (yChange);

    invalidate();
}


public void drag(MotionEvent event) {

    float eventX = event.getX();
    float eventY = event.getY();
    float spacingX = eventX - mStartDragPoint.x;
    float spacingY = eventY - mStartDragPoint.y;
    float newPositionLeft = (dst.left < 0 ? spacingX : spacingX * -1) + dst.left;
    float newPositionRight = (spacingX) + dst.right;
    float newPositionTop = (dst.top < 0 ? spacingY : spacingY * -1) + dst.top;
    float newPositionBottom = (spacingY) + dst.bottom;
    boolean x = true;
    boolean y = true;

    if (newPositionRight < 0.0f || newPositionLeft > 0.0f) {
        if (newPositionRight < 0.0f && newPositionLeft > 0.0f) {
            x = false;
        } else {
            eventX = oldEventX;
            mStartDragPoint.x = oldStartPointX;
        }
    }
    if (newPositionBottom < 0.0f || newPositionTop > 0.0f) {
        if (newPositionBottom < 0.0f && newPositionTop > 0.0f) {
            y = false;
        } else {
            eventY = oldEventY;
            mStartDragPoint.y = oldStartPointY;
        }
    }

    if (mDraggable) {
        if (x) oldEventX = eventX;
        if (y) oldEventY = eventY;
        if (x) oldStartPointX = mStartDragPoint.x;
        if (y) oldStartPointY = mStartDragPoint.y;
    }

}

public void zoom(MotionEvent event) {
    float newDist = spacing(event);
    boolean in = newDist > oldDist;

    if (!in && scale < .01f) {
        return;
    }

    scale = newDist / oldDist;

    int xChange = (int) ((mBitmapWidth * scale) / 2);
    int yChange = (int) ((mBitmapHeight * scale) / 2);

    if (xChange > 10 && yChange > 10) { //ADDED THIS TO KEEP IT FROM GOING INVERSE

    int xMidPoint = ((dst.right - dst.left) / 2) + dst.left;
    int yMidPoint = ((dst.bottom - dst.top) / 2) + dst.top;

    dst.left = (int) (float) (xMidPoint - xChange);
    dst.top = (int) (float) (yMidPoint - yChange);

    dst.right = (int) (float) (xMidPoint + xChange);
    dst.bottom = (int) (float) (yMidPoint + yChange);

    }

    invalidate();

}


/**
 * Determine the space between the first two fingers
 */
private float spacing(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);

    return (float) Math.sqrt(x * x + y * y);
}

/**
 * Calculate the mid point of the first two fingers
 */
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);
}


@Override
public boolean onLongClick(View view) {


    if (mode == DRAG) {
        if ((mStartPoint.x > dst.left && mStartPoint.x < dst.right) && (mStartPoint.y < dst.bottom && mStartPoint.y > dst.top)
                && (mMovePoint.x > dst.left && mMovePoint.x < dst.right) && (mMovePoint.y < dst.bottom && mMovePoint.y > dst.top)) {
            mode = MOVE;
            v.vibrate(500);
        }
    }
    return true;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mode == MOVE) {
        canvas.drawBitmap(mBitmap, src, dst, null);
        canvas.drawBitmap(mBitmap, src, dst, mPaint);
    } else {
        canvas.drawBitmap(mBitmap, src, dst, null);
    }

}
}

... puis ajoutez ceci à votre activité

CustomZoomView customImageView = (CustomZoomView) findViewById(R.id.customZoomView);
customImageView.setBitmap(yourBitmap);

... et ceci à votre vue en XML.

<your.package.name.CustomZoomView
   Android:id="@+id/customZoomView"
   Android:layout_width="fill_parent"
   Android:layout_height="fill_parent"
   Android:longClickable="true"/>

... et ajoutez ceci à votre manifeste

<uses-permission Android:name="Android.permission.VIBRATE"/>
3
a54studio

Voici ma solution, elle est basée sur la solution de @ alexbirkett.

public class ZoomImageView extends ImageView {

// region . Static fields .

static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
static final int CLICK = 3;

// endregion . Static fields .

// region . Fields .

private int mode = NONE;

private Matrix mMatrix = new Matrix();

private PointF mLastTouch = new PointF();
private PointF mStartTouch = new PointF();
private float minScale = 0.5f;
private float maxScale = 4f;
private float[] mCriticPoints;

private float mScale = 1f;
private float mRight;
private float mBottom;
private float mOriginalBitmapWidth;
private float mOriginalBitmapHeight;

private ScaleGestureDetector mScaleDetector;

//endregion . Fields .

// region . Ctor .
public ZoomImageView(Context context) {
    super(context);
    init(context);
}

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

public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context);
}

// endregion . Ctor .

// region . Overrider .

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int bmHeight = getBmHeight();
    int bmWidth = getBmWidth();

    float width = getMeasuredWidth();
    float height = getMeasuredHeight();
    float scale = 1;

    // If image is bigger then display fit it to screen.
    if (width < bmWidth || height < bmHeight) {
        scale = width > height ? height / bmHeight : width / bmWidth;
    }

    mMatrix.setScale(scale, scale);
    mScale = 1f;

    mOriginalBitmapWidth = scale * bmWidth;
    mOriginalBitmapHeight = scale * bmHeight;

    // Center the image
    float redundantYSpace = (height - mOriginalBitmapHeight);
    float redundantXSpace = (width - mOriginalBitmapWidth);

    mMatrix.postTranslate(redundantXSpace / 2, redundantYSpace / 2);

    setImageMatrix(mMatrix);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    mScaleDetector.onTouchEvent(event);

    mMatrix.getValues(mCriticPoints);
    float translateX = mCriticPoints[Matrix.MTRANS_X];
    float trnslateY = mCriticPoints[Matrix.MTRANS_Y];
    PointF currentPoint = new PointF(event.getX(), event.getY());

    switch (event.getAction()) {
        //when one finger is touching
        //set the mode to DRAG
        case MotionEvent.ACTION_DOWN:
            mLastTouch.set(event.getX(), event.getY());
            mStartTouch.set(mLastTouch);
            mode = DRAG;
            break;
        //when two fingers are touching
        //set the mode to ZOOM
        case MotionEvent.ACTION_POINTER_DOWN:
            mLastTouch.set(event.getX(), event.getY());
            mStartTouch.set(mLastTouch);
            mode = ZOOM;
            break;
        //when a finger moves
        //If mode is applicable move image
        case MotionEvent.ACTION_MOVE:

            //if the mode is ZOOM or
            //if the mode is DRAG and already zoomed
            if (mode == ZOOM || (mode == DRAG && mScale > minScale)) {

                // region . Move  image.

                float deltaX = currentPoint.x - mLastTouch.x;// x difference
                float deltaY = currentPoint.y - mLastTouch.y;// y difference
                float scaleWidth = Math.round(mOriginalBitmapWidth * mScale);// width after applying current scale
                float scaleHeight = Math.round(mOriginalBitmapHeight * mScale);// height after applying current scale

                // Move image to lef or right if its width is bigger than display width
                if (scaleWidth > getWidth()) {
                    if (translateX + deltaX > 0) {
                        deltaX = -translateX;
                    } else if (translateX + deltaX < -mRight) {
                        deltaX = -(translateX + mRight);
                    }
                } else {
                    deltaX = 0;
                }
                // Move image to up or bottom if its height is bigger than display height
                if (scaleHeight > getHeight()) {
                    if (trnslateY + deltaY > 0) {
                        deltaY = -trnslateY;
                    } else if (trnslateY + deltaY < -mBottom) {
                        deltaY = -(trnslateY + mBottom);
                    }
                } else {
                    deltaY = 0;
                }

                //move the image with the matrix
                mMatrix.postTranslate(deltaX, deltaY);
                //set the last touch location to the current
                mLastTouch.set(currentPoint.x, currentPoint.y);

                // endregion . Move image .
            }
            break;
        //first finger is lifted
        case MotionEvent.ACTION_UP:
            mode = NONE;
            int xDiff = (int) Math.abs(currentPoint.x - mStartTouch.x);
            int yDiff = (int) Math.abs(currentPoint.y - mStartTouch.y);
            if (xDiff < CLICK && yDiff < CLICK)
                performClick();
            break;
        // second finger is lifted
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
    }
    setImageMatrix(mMatrix);
    invalidate();
    return true;
}

//endregion . Overrides .

// region . Privates .

private void init(Context context) {
    super.setClickable(true);
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    mCriticPoints = new float[9];
    setImageMatrix(mMatrix);
    setScaleType(ScaleType.MATRIX);
}

private int getBmWidth() {
    Drawable drawable = getDrawable();
    if (drawable != null) {
        return drawable.getIntrinsicWidth();
    }
    return 0;
}

private int getBmHeight() {
    Drawable drawable = getDrawable();
    if (drawable != null) {
        return drawable.getIntrinsicHeight();
    }
    return 0;
}

//endregion . Privates .

// region . Internal classes .

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        mode = ZOOM;
        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float scaleFactor = detector.getScaleFactor();
        float newScale = mScale * scaleFactor;
        if (newScale < maxScale && newScale > minScale) {
            mScale = newScale;
            float width = getWidth();
            float height = getHeight();
            mRight = (mOriginalBitmapWidth * mScale) - width;
            mBottom = (mOriginalBitmapHeight * mScale) - height;

            float scaledBitmapWidth = mOriginalBitmapWidth * mScale;
            float scaledBitmapHeight = mOriginalBitmapHeight * mScale;

            if (scaledBitmapWidth <= width || scaledBitmapHeight <= height) {
                mMatrix.postScale(scaleFactor, scaleFactor, width / 2, height / 2);
            } else {
                mMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
            }
        }
        return true;
    }
}

// endregion . Internal classes .
}
3
roroinpho21

Essayez ce qui suit:

package com.example.nwssugeoinformationmobileapplication;
import Android.os.Bundle;
import Android.annotation.SuppressLint;
import Android.app.Activity;
import Android.content.Intent;
import Android.util.FloatMath;
import Android.util.Log;
import Android.view.Menu;
import Android.view.MenuInflater;
import Android.view.MenuItem;
import Android.view.MotionEvent;
import Android.view.View.OnTouchListener;
import Android.widget.TabHost;
import Android.widget.TabHost.TabSpec;
import Android.graphics.Matrix;
import Android.graphics.PointF;
import Android.graphics.RectF;
import Android.graphics.drawable.Drawable;
import Android.view.View;
import Android.widget.ImageView;
public class MainActivity extends Activity implements  OnTouchListener {

    private static final String TAG = "Touch";
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;

    private ImageView view;
    private float[] matrixValues = new float[9];
    private float maxZoom;
    private float minZoom;
    private float height;
    private float width;
    private RectF viewRect;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TabHost th = (TabHost) findViewById (R.id.tabhost);
        th.setup();

        TabSpec specs = th.newTabSpec("tag1");
        specs.setContent(R.id.tab1);
        specs.setIndicator("Map");
        th.addTab(specs);


        specs = th.newTabSpec("tag2");
        specs.setContent(R.id.tab2);
        specs.setIndicator("Search");
        th.addTab(specs);


        view = (ImageView) findViewById(R.id.imageView1);
        Drawable bitmap = getResources().getDrawable(R.drawable.map);
        view.setImageDrawable(bitmap);
        view.setOnTouchListener(this); 

        matrix.setTranslate(1f, 1f);
        view.setImageMatrix(matrix);



    } 



    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if(hasFocus){
    init();
            }
    }
    private void init() {
        maxZoom = 2;
        minZoom = 1f;
        height = view.getDrawable().getIntrinsicHeight();
        width = view.getDrawable().getIntrinsicWidth();
        viewRect = new RectF(0, 0, view.getWidth(), view.getHeight());
        }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menus, menu);
        return true; 
        }

    public boolean onOptionsItemSelected(MenuItem item) {

        if(item.getItemId()== R.id.item1){
            Log.d("Tracks", "Track Us was Clicked");

            startActivity(new Intent (MainActivity.this, Tracklocation.class ));
            }

        if(item.getItemId()== R.id.item2){
            Log.d("Updates", "Updates was Clicked");

            startActivity(new Intent (MainActivity.this, Updates.class ));
            }

        if(item.getItemId()== R.id.item3){
            Log.d("About Us", "About Us was Clicked");


            startActivity(new Intent (MainActivity.this, Horoscope.class ));
            }


        return super.onOptionsItemSelected(item);

     }


    @Override
    public boolean onTouch(View v, MotionEvent rawEvent) {
        ImageView view = (ImageView) v;
        view.setScaleType(ImageView.ScaleType.MATRIX);
        dumpEvent(rawEvent);
    // Handle touch events here...
    switch (rawEvent.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
    savedMatrix.set(matrix);
    start.set(rawEvent.getX(), rawEvent.getY());
    Log.d(TAG, "mode=DRAG");
    mode = DRAG;
    break;
    case MotionEvent.ACTION_POINTER_DOWN:
    oldDist = spacing(rawEvent);
    Log.d(TAG, "oldDist=" + oldDist);
    if (oldDist > 10f) {
    savedMatrix.set(matrix);
    midPoint(mid, rawEvent);
    mode = ZOOM;
    Log.d(TAG, "mode=ZOOM");
    }
    break;
    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_POINTER_UP:
    mode = NONE;
    Log.d(TAG, "mode=NONE");
    break;
    case MotionEvent.ACTION_MOVE:
    if (mode == DRAG) {
    matrix.set(savedMatrix);
    // limit pan
    matrix.getValues(matrixValues);
    float currentY = matrixValues[Matrix.MTRANS_Y];
    float currentX = matrixValues[Matrix.MTRANS_X];
    float currentScale = matrixValues[Matrix.MSCALE_X];
    float currentHeight = height * currentScale;
    float currentWidth = width * currentScale;
    float dx = rawEvent.getX() - start.x;
    float dy = rawEvent.getY() - start.y;
    float newX = currentX+dx;
    float newY = currentY+dy;
    RectF drawingRect = new RectF(newX, newY, newX+currentWidth, newY+currentHeight);
    float diffUp = Math.min(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
    float diffDown = Math.max(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
    float diffLeft = Math.min(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
    float diffRight = Math.max(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);

    if(diffUp > 0 ){
    dy +=diffUp;
    }
    if(diffDown < 0){
    dy +=diffDown;
    }
    if( diffLeft> 0){
    dx += diffLeft;
    }
    if(diffRight < 0){
    dx += diffRight;
    }
    matrix.postTranslate(dx, dy);
    } else if (mode == ZOOM) {
    float newDist = spacing(rawEvent);
    Log.d(TAG, "newDist=" + newDist);
    if (newDist > 10f) {
    matrix.set(savedMatrix);
    float scale1 = newDist / oldDist;
    matrix.getValues(matrixValues);
    float currentScale = matrixValues[Matrix.MSCALE_X];
    // limit zoom
    if (scale1 * currentScale > maxZoom) {
    scale1 = maxZoom / currentScale;
    } else if (scale1 * currentScale < minZoom) {
    scale1 = minZoom / currentScale;
    }
    matrix.postScale(scale1, scale1, mid.x, mid.y);
    }
    }
    break;
    }
    view.setImageMatrix(matrix);
    return true; 
    }

    @SuppressWarnings("deprecation")
    private void dumpEvent(MotionEvent 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(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);
        }
        /** Calculate the mid point of the first two fingers */
        @SuppressLint("FloatMath")
        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);
        }
}
3
nitz opanes jr

Méthode pour appeler la boîte de dialogue À propos de & assistance

 public void setupAboutSupport() {

    try {

        // The About&Support AlertDialog is active
        activeAboutSupport=true;

        View messageView;
        int orientation=this.getResources().getConfiguration().orientation;

        // Inflate the about message contents
        messageView = getLayoutInflater().inflate(R.layout.about_support, null, false);

        ContextThemeWrapper ctw = new ContextThemeWrapper(this, R.style.MyCustomTheme_AlertDialog1);
        AlertDialog.Builder builder = new AlertDialog.Builder(ctw);
        builder.setIcon(R.mipmap.ic_launcher);
        builder.setTitle(R.string.action_aboutSupport);
        builder.setView(messageView);

        TouchImageView imgDisplay = (TouchImageView) messageView.findViewById(R.id.action_infolinks_about_support);
        imgDisplay.setMaxZoom(3f);

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.myinfolinks_about_support);

        int imageWidth = bitmap.getWidth();
        int imageHeight = bitmap.getHeight();
        int newWidth;

        // Calculate the new About_Support image width
        if(orientation==Configuration.ORIENTATION_PORTRAIT ) {
            // For 7" up to 10" tablets
            //if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
            if (SingletonMyInfoLinks.isTablet) {
                    // newWidth = widthScreen - (two borders of about_support layout and 20% of width Screen)
                newWidth = widthScreen - ((2 * toPixels(8)) + (int)(widthScreen*0.2));
            } else newWidth = widthScreen - ((2 * toPixels(8)) + (int)(widthScreen*0.1));

        } else {
            // For 7" up to 10" tablets
            //if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
            if (SingletonMyInfoLinks.isTablet) {
                newWidth = widthScreen - ((2 * toPixels(8)) + (int)(widthScreen*0.5));

            } else newWidth = widthScreen - ((2 * toPixels(8)) + (int)(widthScreen*0.3));
        }

        // Get the scale factor
        float scaleFactor = (float)newWidth/(float)imageWidth;
        // Calculate the new About_Support image height
        int newHeight = (int)(imageHeight * scaleFactor);
        // Set the new bitmap corresponding the adjusted About_Support image
        bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);

        // Rescale the image
        imgDisplay.setImageBitmap(bitmap);

        dialogAboutSupport = builder.show();

        TextView textViewVersion = (TextView) dialogAboutSupport.findViewById(R.id.action_strVersion);
        textViewVersion.setText(Html.fromHtml(getString(R.string.aboutSupport_text1)+" <b>"+versionName+"</b>"));

        TextView textViewDeveloperName = (TextView) dialogAboutSupport.findViewById(R.id.action_strDeveloperName);
        textViewDeveloperName.setText(Html.fromHtml(getString(R.string.aboutSupport_text2)+" <b>"+SingletonMyInfoLinks.developerName+"</b>"));

        TextView textViewSupportEmail = (TextView) dialogAboutSupport.findViewById(R.id.action_strSupportEmail);
        textViewSupportEmail.setText(Html.fromHtml(getString(R.string.aboutSupport_text3)+" "+SingletonMyInfoLinks.developerEmail));

        TextView textViewCompanyName = (TextView) dialogAboutSupport.findViewById(R.id.action_strCompanyName);
        textViewCompanyName.setText(Html.fromHtml(getString(R.string.aboutSupport_text4)+" "+SingletonMyInfoLinks.companyName));

        Button btnOk = (Button) dialogAboutSupport.findViewById(R.id.btnOK);

        btnOk.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialogAboutSupport.dismiss();
            }
        });

        dialogAboutSupport.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(final DialogInterface dialog) {
                // the About & Support AlertDialog is closed
                activeAboutSupport=false;
            }
        });

        dialogAboutSupport.getWindow().setBackgroundDrawable(new ColorDrawable(SingletonMyInfoLinks.atualBackgroundColor));

        /* Effect that image appear slower */
        // Only the fade_in matters
        AlphaAnimation fade_out = new AlphaAnimation(1.0f, 0.0f);
        AlphaAnimation fade_in = new AlphaAnimation(0.0f, 1.0f);
        AlphaAnimation a = false ? fade_out : fade_in;

        a.setDuration(2000); // 2 sec
        a.setFillAfter(true); // Maintain the visibility at the end of animation
        // Animation start
        ImageView img = (ImageView) messageView.findViewById(R.id.action_infolinks_about_support);
        img.startAnimation(a);

    } catch (Exception e) {
        //Log.e(SingletonMyInfoLinks.appNameText +"-" +  getLocalClassName() + ": ", e.getMessage());
    }
}
2
jmtsilva69

Si vous souhaitez définir l'échelle d'une image avant de l'afficher, utilisez cette classe: https://github.com/MikeOrtiz/TouchImageView/blob/master/src/com/ortiz/touch/TouchImageView.Java .

De plus, l'image peut être redimensionnée avec un double tapotement.

Si vous utilisez la ImageView dans une ViewPager, appliquez ce correctif: https://github.com/MikeOrtiz/TouchImageView/issues/125 .

0
CoolMind

ZoomLib Link: https://drive.google.com/uc?export=download&id=0B34PUThnUsjVaHpkaGk0Z1hSRU0

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dummy_layout_for_zooming);// Activity layout 
mZoomLinearLayout = (LinearLayout) findViewById(R.id.mZoomLinearLayout);// LinearLayout inside Activity layout
View v = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.layout_for_zoom, null, false);// View wants to zoom
v.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));
ZoomView zoomView = new ZoomView(this);// intialize lib
zoomView.addView(v);
mZoomLinearLayout.addView(zoomView);
}
0
Saurabh Bhandari

Je sais qu'il est un peu tard pour cette réponse, mais j'espère que cela aidera quelqu'un.

Je cherchais la même chose (Zoom avec pincement et déplacement d’image) et j’ai trouvé ce lien Blog des développeurs Android .

Fonctionne parfaitement. Aucun artefact ou quoi que ce soit. Il utilise ScaleGestureDetector.

0
Mahsa

Il suffit de changer ACTION_MOVE_EVENT in Chirag Raval Réponse pour définir ZOOM_IN LIMIT

float[] values = new float[9]; matrix.getValues(values);
                //0.37047964 is limit for zoom in
                if(values[Matrix.MSCALE_X]>0.37047964) {
                    matrix.set(savedMatrix);
                    matrix.postScale(scale, scale, mid.x, mid.y);
                    view.setImageMatrix(matrix);
                }else if (scale>1){
                    matrix.set(savedMatrix);
                    matrix.postScale(scale, scale, mid.x, mid.y);
                    view.setImageMatrix(matrix);
                }
0
shashank sachdev

C'est vieux, mais cela peut aider quelqu'un d'autre.

La classe TouchImageView ci-dessous prend en charge le zoom avant/arrière avec pincement ou double frappe

import Android.content.Context;
import Android.graphics.Matrix;
import Android.graphics.PointF;
import Android.graphics.drawable.Drawable;
import Android.util.AttributeSet;
import Android.util.Log;
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 implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {

    Matrix matrix;

    // We can be in one of these 3 states
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;

    // Remember some things for zooming
    PointF last = new PointF();
    PointF start = new PointF();
    float minScale = 1f;
    float maxScale = 3f;
    float[] m;

    int viewWidth, viewHeight;
    static final int CLICK = 3;
    float saveScale = 1f;
    protected float origWidth, origHeight;
    int oldMeasuredWidth, oldMeasuredHeight;

    ScaleGestureDetector mScaleDetector;

    Context context;

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

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

    GestureDetector mGestureDetector;

    private void sharedConstructing(Context context) {
        super.setClickable(true);
        this.context = context;
        mGestureDetector = new GestureDetector(context, this);
        mGestureDetector.setOnDoubleTapListener(this);

        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        matrix = new Matrix();
        m = new float[9];
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mScaleDetector.onTouchEvent(event);
                mGestureDetector.onTouchEvent(event);

                PointF curr = new PointF(event.getX(), event.getY());

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        last.set(curr);
                        start.set(last);
                        mode = DRAG;
                        break;

                    case MotionEvent.ACTION_MOVE:
                        if (mode == DRAG) {
                            float deltaX = curr.x - last.x;
                            float deltaY = curr.y - last.y;
                            float fixTransX = getFixDragTrans(deltaX, viewWidth,
                                    origWidth * saveScale);
                            float fixTransY = getFixDragTrans(deltaY, viewHeight,
                                    origHeight * saveScale);
                            matrix.postTranslate(fixTransX, fixTransY);
                            fixTrans();
                            last.set(curr.x, curr.y);
                        }
                        break;

                    case MotionEvent.ACTION_UP:
                        mode = NONE;
                        int xDiff = (int) Math.abs(curr.x - start.x);
                        int yDiff = (int) Math.abs(curr.y - start.y);
                        if (xDiff < CLICK && yDiff < CLICK)
                            performClick();
                        break;

                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        break;
                }

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

        });
    }

    public void setMaxZoom(float x) {
        maxScale = x;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        // Double tap is detected
        Log.i("MAIN_TAG", "Double tap detected");
        float origScale = saveScale;
        float mScaleFactor;

        if (saveScale == maxScale) {
            saveScale = minScale;
            mScaleFactor = minScale / origScale;
        } else {
            saveScale = maxScale;
            mScaleFactor = maxScale / origScale;
        }

        matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2,
                viewHeight / 2);

        fixTrans();
        return false;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }

    private class ScaleListener extends
            ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            mode = ZOOM;
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float mScaleFactor = detector.getScaleFactor();
            float origScale = saveScale;
            saveScale *= mScaleFactor;
            if (saveScale > maxScale) {
                saveScale = maxScale;
                mScaleFactor = maxScale / origScale;
            } else if (saveScale < minScale) {
                saveScale = minScale;
                mScaleFactor = minScale / origScale;
            }

            if (origWidth * saveScale <= viewWidth
                    || origHeight * saveScale <= viewHeight)
                matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2,
                        viewHeight / 2);
            else
                matrix.postScale(mScaleFactor, mScaleFactor,
                        detector.getFocusX(), detector.getFocusY());

            fixTrans();
            return true;
        }
    }

    void fixTrans() {
        matrix.getValues(m);
        float transX = m[Matrix.MTRANS_X];
        float transY = m[Matrix.MTRANS_Y];

        float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
        float fixTransY = getFixTrans(transY, viewHeight, origHeight
                * saveScale);

        if (fixTransX != 0 || fixTransY != 0)
            matrix.postTranslate(fixTransX, fixTransY);
    }

    float getFixTrans(float trans, float viewSize, float contentSize) {
        float minTrans, maxTrans;

        if (contentSize <= viewSize) {
            minTrans = 0;
            maxTrans = viewSize - contentSize;
        } else {
            minTrans = viewSize - contentSize;
            maxTrans = 0;
        }

        if (trans < minTrans)
            return -trans + minTrans;
        if (trans > maxTrans)
            return -trans + maxTrans;
        return 0;
    }

    float getFixDragTrans(float delta, float viewSize, float contentSize) {
        if (contentSize <= viewSize) {
            return 0;
        }
        return delta;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewWidth = MeasureSpec.getSize(widthMeasureSpec);
        viewHeight = MeasureSpec.getSize(heightMeasureSpec);

        //
        // Rescales image on rotation
        //
        if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
                || viewWidth == 0 || viewHeight == 0)
            return;
        oldMeasuredHeight = viewHeight;
        oldMeasuredWidth = viewWidth;

        if (saveScale == 1) {
            // Fit to screen.
            float scale;

            Drawable drawable = getDrawable();
            if (drawable == null || drawable.getIntrinsicWidth() == 0
                    || drawable.getIntrinsicHeight() == 0)
                return;
            int bmWidth = drawable.getIntrinsicWidth();
            int bmHeight = drawable.getIntrinsicHeight();

            Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);

            float scaleX = (float) viewWidth / (float) bmWidth;
            float scaleY = (float) viewHeight / (float) bmHeight;
            scale = Math.min(scaleX, scaleY);
            matrix.setScale(scale, scale);

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

            matrix.postTranslate(redundantXSpace, redundantYSpace);

            origWidth = viewWidth - 2 * redundantXSpace;
            origHeight = viewHeight - 2 * redundantYSpace;
            setImageMatrix(matrix);
        }
        fixTrans();
    }
}

Utilisation: Vous pouvez remplacer votre ImageView par TouchImageView en XML et en Java.

1. Pour XML

<?xml version="1.0" encoding="utf-8"?>
<com.example.Android.myapp.TouchImageView 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/imViewedImage"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:clickable="true"
    Android:focusable="true" />

2. Pour Java

TouchImageView imViewedImage = findViewById(R.id.imViewedImage);
0
M.Zain