具有全屏缩放的 ImageView

Posted

技术标签:

【中文标题】具有全屏缩放的 ImageView【英文标题】:ImageView with fullscreen zoom 【发布时间】:2018-05-10 16:41:07 【问题描述】:

我正在通过 Glide 从云端将图像加载到我的回收站视图的 ImageView 中。 我想要的是在单击这些图像中的每一个时,图像应该是 全屏 并具有捏缩放功能。谢谢

【问题讨论】:

android Image View Pinch Zooming的可能重复 你有什么尝试吗?代码..? 使用以下代码@Sobinscott 图片在回收站视图中,通过 Glide 加载。图像应该在点击时全屏显示,并且也应该可以缩放。希望你清楚 你试过这个吗:developer.android.com/training/animation/zoom.html 【参考方案1】:

有一种更简单的方法可以实现这一点。尝试使用名为StfalconImageViewer 的库。它支持开箱即用的图像打开和关闭、捏合缩放和滑动关闭手势的过渡动画。使用 Glide 会这样完成:

new StfalconImageViewer.Builder<>(context, images, new ImageLoader<String>() 
            @Override
            public void loadImage(ImageView imageView, String imageUrl) 
                Glide.with(context).load(imageUrl).into(imageView)
            
        ).show();

【讨论】:

【参考方案2】:

您可以通过 2 种方式实现这一目标

    RecyclerView 上的可见 imageView 打开另一个Activity并在其中显示图像

使用这个自定义类进行缩放

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

【讨论】:

你能分享使用这个类的最小代码吗?谢谢 如果你把这个类放在 com.example.ZoomableImageView 然后在 xml 你可以在xml中使用这个ZoomableImageView,就像在Xml中简单的ImageView声明一样 像这样 和java文件ZoomableImageView aiv = (ZoomableImageView) findViewbyId(); 我尝试了一个示例。但是图像没有显示并且没有抛出任何异常&lt;com.tst.android.zoom.ZoomableImageView android:id="@+id/imageView8" android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/cat"/&gt; @Sobinscott 您必须使用 setImageBitmap() 来设置图像。您的 XML 将调用 setDrawable() 并且这不起作用。我将该类转换为 C# 以将其与 Xamarin Android 一起使用,它工作正常。

以上是关于具有全屏缩放的 ImageView的主要内容,如果未能解决你的问题,请参考以下文章

Libgdx 未缩放全屏

在 Fabric.js 中全屏显示画布

UIScrollView 中的 UIImageView 不是全屏和捏缩放

VM VirtualBox 全屏模式 && 自动缩放模式 相互切换

防止 MPMoviePlayerController 在全屏时旋转和缩放为纵向

Qt 5.10 QGraphicsView 无法将 QGraphicsScene 缩放到全屏