Android使用SubsamplingScaleImageView完美查看超大图片

Android使用SubsamplingScaleImageView完美查看超大图片

一、目标

在神马笔记中查看《溪山清远图》。

二、体验地址

神马笔记最新版本下载:【神马笔记 版本2.2.0——功能优化.apk

三、实现方案

1. SubsamplingScaleImageView

在《Android加载超大图片》一文中,我们已经介绍过SubsamplingScaleImageView的基础用法。

这里结合SubsamplingScaleImageView的功能来提高图片浏览体验。

2. OnStateChangedListener

使用OnStateChangedListener可以监听到SubsamplingScaleImageView的缩放和移动事件。

2D图片有3个维度的操作:

  1. 位置——移动图片
  2. 大小——缩放图片
  3. 角度——旋转图片

SubsamplingScaleImageView不支持第3个维度——角度。

因此只有移动和缩放2个事件。

通过OnStateChangedListener,我们可以实现当用户进行缩放或者移动,或者2者同时发生时,自动全屏。

全屏之后,图片变不会被菜单栏所遮挡,可以看到全部图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* An event listener, allowing activities to be notified of pan and zoom events. Initialisation
* and calls made by your code do not trigger events; touch events and animations do. Methods in
* this listener will be called on the UI thread and may be called very frequently - your
* implementation should return quickly.
*/
@SuppressWarnings("EmptyMethod")
public interface OnStateChangedListener {

/**
* The scale has changed. Use with {@link #getMaxScale()} and {@link #getMinScale()} to determine
* whether the image is fully zoomed in or out.
* @param newScale The new scale.
* @param origin Where the event originated from - one of {@link #ORIGIN_ANIM}, {@link #ORIGIN_TOUCH}.
*/
void onScaleChanged(float newScale, int origin);

/**
* The source center has been changed. This can be a result of panning or zooming.
* @param newCenter The new source center point.
* @param origin Where the event originated from - one of {@link #ORIGIN_ANIM}, {@link #ORIGIN_TOUCH}.
*/
void onCenterChanged(PointF newCenter, int origin);

}

3. setDoubleTapZoomScale

通过setDoubleTapZoomScale接口,可以设置双击图片的缩放系数。

因为SubsamplingScaleImageView初始显示时,使整张图片居中显示。即最长的一边完全显示在屏幕内。

因此,我们设置双击图片时,将最短的一边完全显示在屏幕内。

并且当长宽比一致时,设置为2倍大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static float getDoubleTapScale(int width, int height, int viewWidth, int viewHeight) {
if (viewWidth <= 0 || viewHeight <= 0) {
return 1;
}

float sx = viewWidth * 1.f / width;
float sy = viewHeight * 1.f / height;

float scale = Math.max(sx, sy);
if (Math.abs(sx - sy) < Float.MIN_NORMAL) {
scale = 2 * sx;
}

return scale;
}

四、Finally

~倚遍阑干~只是无情绪~