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

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

【问题讨论】:

标签: android imageview zooming


【解决方案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 种方式实现这一目标

    1. RecyclerView 上的可见 imageView
    2. 打开另一个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 一起使用,它工作正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    相关资源
    最近更新 更多