Android实现ImageView图片双击放大及缩小
作者:BetterLaterThanNever 发布时间:2022-04-07 10:34:06
标签:Android,ImageView,图片放大,图片缩小
本文实例介绍了Android实现ImageView图片双击放大及缩小的相关技巧,分享给大家供大家参考,具体内容如下
public class DoubleScaleImageView extends ImageView implements OnTouchListener, OnGlobalLayoutListener {
private boolean isFirst = false;
private float doubleScale;// 双击放大的值
private Matrix mScaleMatrix;
private float defaultScale;// 默认的缩放值
private int mLastPinterCount;// 记录上一次多点触控的数量
private float mLastX;
private float mLastY;
private int mTouchSlop;
private boolean isCanDrag;
private boolean isCheckLeft;
private boolean isCheckTop;
private GestureDetector mGestureDetector;
public DoubleScaleImageView(Context context) {
this(context, null);
}
public DoubleScaleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@SuppressLint("ClickableViewAccessibility")
public DoubleScaleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScaleMatrix = new Matrix();
setScaleType(ScaleType.MATRIX);
setOnTouchListener(this);
// getScaledTouchSlop是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件。如果小于这个距离就不触发移动控件
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
float x = e.getX();
float y = e.getY();
if (getScale() < doubleScale) {
mScaleMatrix.postScale(doubleScale / getScale(), doubleScale / getScale(), x, y);// 放大
}
else {
mScaleMatrix.postScale(defaultScale / getScale(), defaultScale / getScale(), x, y);// 缩小
}
setImageMatrix(mScaleMatrix);
return super.onDoubleTap(e);
}
});
}
@Override
protected void onAttachedToWindow() {// view附加到窗体上时调用该方法
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@SuppressWarnings("deprecation")
@Override
protected void onDetachedFromWindow() {// 将视图从窗体上分离的时候调用该方法。
super.onDetachedFromWindow();
getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
@Override
public void onGlobalLayout() {// 在这个方法中获取ImageView加载完成后的图片
if (!isFirst) {
// 获取控件的宽度和高度
int width = getWidth();
int height = getHeight();
// 得到我们的图片以及图片的宽度及高度
Drawable drawable = getDrawable();
if (drawable == null) { return; }
int imageWidth = drawable.getIntrinsicWidth();// 图片的宽度
int imageHeight = drawable.getIntrinsicHeight();// 图片的高度
float scale = 1.0f;
// 如果图片宽度大于控件宽度,但是图片高度小于控件 高度,我们要缩小图片
if (imageWidth > width && imageHeight < height) {
scale = width * 1.0f / imageWidth;
}
// 如果图片宽度小于控件宽度,但是图片高度大于控件 高度,我们要缩小图片
if (imageWidth < width && imageHeight > height) {
scale = height * 1.0f / imageHeight;
}
// 如果图片的宽度都 大于或小于控件宽度,我们则要对图片进行对应缩放,保证图片占满控件
if ((imageWidth > width && imageHeight > height) || (imageWidth < width && imageHeight < height)) {
scale = Math.min(width * 1.0f / imageWidth, height * 1.0f / imageHeight);
}
// 初始化对应的缩放值
defaultScale = scale;
doubleScale = defaultScale * 2;
// 图片缩放后,将图片要移动到控件中心
int dx = width / 2 - imageWidth / 2;
int dy = height / 2 - imageHeight / 2;
mScaleMatrix.postTranslate(dx, dy);
mScaleMatrix.postScale(defaultScale, defaultScale, width / 2, height / 2);
setImageMatrix(mScaleMatrix);
isFirst = true;
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mGestureDetector.onTouchEvent(event)) { return true; }
float x = 0;
float y = 0;
int pointerCount = event.getPointerCount();// 获取放在屏幕上的手指数量
for (int i = 0; i < pointerCount; i++) {
x += event.getX(i);
y += event.getY(i);
}
x /= pointerCount;
y /= pointerCount;
if (mLastPinterCount != pointerCount) {
isCanDrag = false;
mLastX = x;
mLastY = y;
}
mLastPinterCount = pointerCount;
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
float dx = x - mLastX;
float dy = y - mLastY;
isCanDrag = isMove(dx, dy);
if (isCanDrag) {
RectF rectf = getMatrixRectf();
if (null != getDrawable()) {
isCheckLeft = isCheckTop = true;
if (rectf.width() < getWidth()) {// 如果图片宽度小于控件宽度(屏幕宽度)不允许横向移动
dx = 0;
isCheckLeft = false;
}
if (rectf.height() < getHeight()) {// 如果图片高度小于控件高度(屏幕高度)不允许纵向移动
dy = 0;
isCheckTop = false;
}
mScaleMatrix.postTranslate(dx, dy);
checkTranslateWithBorder();
setImageMatrix(mScaleMatrix);
}
}
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mLastPinterCount = 0;
break;
}
return true;
}
/**
* 移动图片时进行边界检查
* @description:
* @date 2016-1-8 下午4:02:24
*/
private void checkTranslateWithBorder() {
RectF rectf = getMatrixRectf();
float delX = 0;
float delY = 0;
int width = getWidth();
int height = getHeight();
if (rectf.top > 0 && isCheckTop) {
delY = -rectf.top;
}
if (rectf.bottom < height && isCheckTop) {
delY = height - rectf.bottom;
}
if (rectf.left > 0 && isCheckLeft) {
delX = -rectf.left;
}
if (rectf.right < width && isCheckLeft) {
delX = width - rectf.right;
}
mScaleMatrix.postTranslate(delX, delY);
}
// 判断是否有移动
private boolean isMove(float x, float y) {
return Math.sqrt(x * x + y * y) > mTouchSlop;
}
/**
* 获取图片的位置
* @description:
* @date 2016-1-8 上午9:02:10
*/
private RectF getMatrixRectf() {
Matrix matrix = mScaleMatrix;
RectF recft = new RectF();
if (getDrawable() != null) {
recft.set(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
matrix.mapRect(recft);
}
return recft;
}
// 获取当前图片的缩放值
private float getScale() {
float values[] = new float[9];
mScaleMatrix.getValues(values);
return values[Matrix.MSCALE_X];
}
}


猜你喜欢
- 以下是tcp socket客户端和服务端源码,代码简单大家参考使用吧Tcp Server#include <WinSock2.h>
- 我已经很精简了,两篇(Spring Boot启动过程(一)、spring Boot启动过程(二))依然没写完,接着来。refreshCont
- 开场白我本来是一名android开发者,突然就对java后端产生了浓烈的兴趣。所以,立马就转到了后端。第一个项目使用的使用Spring Da
- 1. 多行编辑先来体验一下从xml文件拷贝字段新建实体对象一般我们为了新建多表连接后映射的 ResultMap ,耗费不少时间,那么我们就来
- 本文将介绍如何在spring boot中集成ehcache作为hibernate的二级缓存。各个框架版本如下spring boot:1.4.
- 1. Text日常最常用的应该就是显示文字,所以有必要说一下Text控件。首先源码如下:@Composablefun Text(  
- 什么是委托?之前写了事件的介绍:https://www.jb51.net/article/59461.htm这里也把委托相关知识也总结一下。
- 前言最近接手了一个老项目,“愉悦的心情”自然无以言表,做开发的朋友都懂,这里就不多说了,都是泪...
- SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案。标准的MVC设计模式,将整个系统划分为显示层、Co
- 前言:反射(Reflection)是.NET提供给开发者的一个强大工具,尽管作为.NET框架的使用者,很多时候不会用到反射。但在一些情况下,
- 一、开源项目 Javascript .NET地址: http://javascriptdotnet.codeplex.com/ 它是Goog
- Kotlin 面向对象这几天一直在准备考试,实在没有时间,已经过去了这么久,终于要到面向对象了!先看看Kotlin中的类长什么样吧.可以看到
- 一. Dispatchers.IO1.Dispatchers.IO在协程中,当需要执行IO任务时,会在上下文中指定Dispatchers.I
- 简介Java 在 1.5 引入了泛型机制,泛型本质是参数化类型,也就是说变量的类型是一个参数,在使用时再指定为具体类型。泛型可以用于类、接口
- 前言在上一篇通知服务NotificationListenerService使用方法 中,我们已经介绍了如何使用NotificationLis
- WebService服务端代码public class WebServiceDemo : System.Web.Services.WebSe
- 使用Zenject和UniRx的入门级技术实现了伪登录注册功能。运行效果登录面板using System;using UniRx;using
- 在上个月的对C#开发微信门户及应用做了介绍,写过了几篇的随笔进行分享,由于时间关系,间隔了一段时间没有继续写这个系列的博客了,并不是对这个方
- 一般在web应用中,对客户端提交上来的图片肯定需要进行压缩的。尤其是比较大的图片,如果不经过压缩会导致页面变的很大,打开速度比较慢,当然了如
- 在开发中,我们经常使用到ListView这个控件。Android的API也提供了许多创建ListView适配器的快捷方式。例如A