package cn.icheny.guide_map;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
/**
* 可手势缩放移动双击缩放ImageView
*
* @author www.icheny.cn
* @date 2017/8/15
*/
public class MapView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener, ScaleGestureDetector.OnScaleGestureListener {
private boolean isPicLoaded = false;//图片是否已加载
float SCALE_MIN = 0.5f;//最小缩小比例值系数
float SCALE_ADAPTIVE = 1.0f;//自适应ViewGroup(或屏幕)缩放比例值
float SCALE_MID = 2.0f;//中间放大比例值系数,双击一次的放大值
float SCALE_MAX = 5.0f;//最大放大比例值系数,双击两次的放大值
private Matrix mScaleMatrix;//缩放矩阵
private ScaleGestureDetector mScaleGestureDetector;//缩放手势探测测器
private GestureDetector mGestureDetector;//手势探测器
private boolean isAutoScaling = false;//是否处于自动缩放中,用于是否响应双击手势的flag
private int mTouchSlop;
public MapView(Context context) {
this(context, null);
}
public MapView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setScaleType(ScaleType.MATRIX);
mScaleMatrix = new Matrix();
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mGestureDetector = initGestureDetector(context);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
/**
* 初始化手势探测器
*
* @param context
* @return GestureDetector
*/
private GestureDetector initGestureDetector(Context context) {
GestureDetector.SimpleOnGestureListener listner = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (!isAutoScaling) {//如果不在自动缩放
isAutoScaling = true;
float x = e.getX();//双击触点x坐标
float y = e.getY();//双击触点y坐标
float scale = getDrawableScale();
if (scale < SCALE_MID) {//当前缩放比例小于一级缩放比例
//一级放大
post(new AutoScaleTask(SCALE_MID, x, y));
} else if (scale >= SCALE_MID && scale < SCALE_MAX) {//当前缩放比例在一级缩放和二级缩放比例之间
//二级放大
post(new AutoScaleTask(SCALE_MAX, x, y));
} else if (scale == SCALE_MAX) {//当前缩放比例等于二级缩放比例
//缩小至自适应view比例
post(new AutoScaleTask(SCALE_ADAPTIVE, x, y));
} else {
isAutoScaling = false;
}
}
return super.onDoubleTap(e);
}
};
return new GestureDetector(context, listner);
}
/**
* 订阅者的onGlobalLayout函数
*/
@Override
public void onGlobalLayout() {
if (!isPicLoaded) {
Drawable drawable = getDrawable();
if (null == drawable) {//图片不存在就继续监听
return;
}
isPicLoaded = true;//图片存在,已加载完成,停止监听
//获取图片固有的宽高(不是指本身属性:分辨率,因为android系统在加载显示图片前可能对其压缩)
int iWidth = drawable.getIntrinsicWidth();
int iHeight = drawable.getIntrinsicHeight();
//获取当前View(ImageView)的宽高,即父View给予的宽高
int width = getWidth();
int height = getHeight();
//对比图片宽高和当前View的宽高,针对性的缩放
if (iWidth >= width && iHeight <= height) {//如果图片固宽大于View宽,固高小于View高,
SCALE_ADAPTIVE = height * 1f / iHeight; // 那么只需针对高度等比例放大图片(这里有别于查看大图的处理方式)
} else if (iWidth <= width && iHeight >= height) {//固宽小于View宽,固高大于View高,针对宽度放大
SCALE_ADAPTIVE = width * 1f / iWidth;
} else if (iWidth >= width && iHeight >= height || iWidth <= width && iHeight <= height) {//固宽和固高都大于或都小于View的宽高,
SCALE_ADAPTIVE = Math.max(width * 1f / iWidth, height * 1f / iHeight);//只取对宽和对高之间最小的缩放比例值(这里有别于查看大图的处理方式)
}
//先将图片移动到View中心位置
mScaleMatrix.postTranslate((width - iWidth) * 1f / 2, (height - iHeight) * 1f / 2);
//再对图片从View的中心点缩放
mScaleMatrix.postScale(SCALE_ADAPTIVE, SCALE_ADAPTIVE, width * 1f / 2, height * 1f / 2);
//执行偏移和缩放
setImageMatrix(mScaleMatrix);
onChangedListner.onChanged(getMatrixRect());
//根据当前图片的缩放情况,重新调整图片的最大最小缩放值
SCALE_MAX *= SCALE_ADAPTIVE;
SCALE_MID *= SCALE_ADAPTIVE;
SCALE_MIN *= SCALE_ADAPTIVE;
}
}
/**
* 缩放手势开始时调用该方法
*
* @param detector
* @return
*/
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
//返回为true,则缩放手势事件往下进行,否则到此为止,即不会执行onScale和onScaleEnd方法
return true;
}
/**
* 缩放手势进行时调用该方法
* 缩放控制范围:SCALE_MIN——SCALE_MAX
*
* @param detector
*/
@Override
public boolean onScale(ScaleGestureDetector detector) {
if (getDrawable() == null) {
return true;//没有图片就不用折腾了
}
//缩放因子(即将缩放的值)
float scaleFactor = detector.getScaleFactor();
//当前图片已缩放的值(如果onScale第一次被调用,scale就是自适应后的缩放值:SCALE_ADAPTIVE)
float scale = getDrawableScale();
//当前缩放值在最大放大值以内且手势检测缩放因子为缩小手势(小于1),或当前缩放值在最小缩小值以内且缩放因子为放大手势,允许缩放
if (scale <= SCALE_MAX && scaleFactor < 1 || scale >= SCALE_MIN && scaleFactor > 1) {
//进一步考虑即将缩小后的缩放比例(scale*scaleFactor)低于规定SCALE_MIN-SCALE_MAX范围的最小值SCALE_MIN
if (scale * scaleFactor < SCALE_MIN && scaleFactor < 1) {
//强制锁定缩小后缩放比例为SCALE_MIN(scale*scaleFactor=SCALE_MIN)
scaleFactor = SCALE_MIN / scale;
}
//进一步考虑即将放大后的缩放比例(scale*scaleFactor)高于规定SCALE_MIN-SCALE_MAX范围的最大值SCALE_MAX
if (scale * scaleFactor > SCALE_MAX && scaleFactor > 1) {
//强制锁定放大后缩放比例为SCALE_MAX(scale*scaleFactor=SCALE_MAX)
scaleFactor = SCALE_MAX / scale;
}
//设定缩放值和缩放位
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
GuideMap.zip (38个子文件)
GuideMap
gradlew.bat 2KB
gradlew 5KB
gradle.properties 747B
app
proguard-rules.pro 942B
src
test
java
cn
icheny
guide_map
ExampleUnitTest.java 413B
androidTest
java
cn
icheny
guide_map
ExampleInstrumentedTest.java 768B
main
res
mipmap-xxxhdpi
ic_launcher.png 10KB
ic_launcher_round.png 14KB
drawable-xhdpi
location.png 3KB
zhaoliyin.jpg 268KB
drawable
mipmap-hdpi
ic_launcher.png 3KB
ic_launcher_round.png 4KB
values
colors.xml 214B
map_ids.xml 108B
map_attr.xml.xml 309B
strings.xml 74B
styles.xml 392B
mipmap-xxhdpi
ic_launcher.png 8KB
ic_launcher_round.png 10KB
mipmap-mdpi
ic_launcher.png 2KB
ic_launcher_round.png 2KB
mipmap-xhdpi
ic_launcher.png 5KB
ic_launcher_round.png 6KB
layout
activity_main.xml 401B
java
cn
icheny
guide_map
MapView.java 18KB
Marker.java 1KB
MainActivity.java 2KB
MapContainer.java 8KB
AndroidManifest.xml 936B
.gitignore 8B
build.gradle 894B
libs
GuideMap.iml 862B
gradle
wrapper
gradle-wrapper.jar 52KB
gradle-wrapper.properties 236B
.gitignore 127B
local.properties 476B
settings.gradle 16B
build.gradle 521B
共 38 条
- 1
资源评论
皓煙
- 粉丝: 112
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功