具有全屏缩放的 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<com.tst.android.zoom.ZoomableImageView android:id="@+id/imageView8" android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/cat"/>
@Sobinscott 您必须使用 setImageBitmap() 来设置图像。您的 XML 将调用 setDrawable() 并且这不起作用。我将该类转换为 C# 以将其与 Xamarin Android 一起使用,它工作正常。以上是关于具有全屏缩放的 ImageView的主要内容,如果未能解决你的问题,请参考以下文章
UIScrollView 中的 UIImageView 不是全屏和捏缩放
VM VirtualBox 全屏模式 && 自动缩放模式 相互切换