上一节我们是通过重写自定义View的onTouchEvent方法来实现我们的图片放大缩小功能的,我们也发现现在app中,图片预览功能很常见的,用户基本已经形成条件反射,看到小图,点击看大图,看到大图两个手指开始进行放大,放大后,开始移动到指定部位,实际上,Android系统本身也是有手势检测这个类来帮助我们实现相关功能的。
首先了解要用到的几个类:
Matrix
在图像处理方面,主要是用于平面的缩放、平移、旋转等操作。Android中的Matrix是一个3 x 3的矩阵,可以使用setValues(float[] values)进行初始化,其内容如下:
{
MSCALE_X, MSKEW_X, MTRANS_X,
MSKEW_Y, MSCALE_Y, MTRANS_Y,
MPERSP_0, MPERSP_1, MPERSP_2
}
Matrix的对图像的处理可分为四类基本变换:
Translate 平移变换
Rotate 旋转变换
Scale 缩放变换
Skew 倾斜变换
针对每种变换,Android提供了pre、set和post三种操作方式。其中
set用于设置Matrix中的值。
pre是先乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。先乘相当于矩阵运算中的右乘。
post是后乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。后乘相当于矩阵运算中的左乘。
具体的用法我们可以看下api说明
GestureDetector
一共有三个监听器——OnDoubleTapListener、OnGestureListener、SimpleOnGestureListener。具体的可以自己看API,能够捕捉到长按、双击什么的
ScaleGestureDetector
嗯,有点像继承来的,其实不是的,独立的一个类,用于检测缩放的手势
下面做一个图片浏览器的效果,使用ViewPager让用户可以滑动切换图片,通过手势实现用户对图片的放大缩小
扩展ImageView,当图片加载时,将图片在屏幕中居中;图片宽或高大于屏幕的,缩小至屏幕大小;可以自由对图片进行放大或缩小
先把代码贴上,然后详细的说明
public class ZoomImageView extends ImageView implements
ViewTreeObserver.OnGlobalLayoutListener
{
public static final float SCALE_MAX = 4.0f;
/**
* 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0
*/
private float initScale = 1.0f;
/**
* 用于存放矩阵的9个值
*/
private final float[] matrixValues = new float[9];
private boolean once = true;
/**
* 缩放的手势检测
*/
private ScaleGestureDetector mScaleGestureDetector;
private final Matrix mScaleMatrix = new Matrix();
public ZoomImageView(Context context) {
this(context, null);
}
public ZoomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
super.setScaleType(ScaleType.MATRIX);
initGestureDector(context);
服务器托管网 }
/**
* 初始化缩放手势检测类
* @param context
*/
private void initGestureDector(Context context) {
mScaleGestureDetector = new ScaleGestureDetector(context,
new OnScaleGestureListener() {
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scale = getScale();
float scaleFactor = detector.getScaleFactor();
if (getDrawable() == null)
return true;
/**
* 缩放的范围控制
*/
if ((scale 1.0f)
|| (scale > initScale && scaleFactor SCALE_MAX) {
scaleFactor = SCALE_MAX / scale;
}
/**
* 设置缩放比例
*/
mScaleMatrix.postScale(scaleFactor, scaleFactor,
detector.getFocusX(), detector.getFocusY());
checkBorder();
setImageMatrix(mScaleMatrix);
}
return true;
}
});
}
/**
* 在缩放时,进行图片显示范围的控制
*/
private void checkBorder() {
RectF rect = getMatrixRectF();
float deltaX = 0;
float deltaY = 0;
int width = getWidth();
int height = getHeight();
// 如果宽或高大于屏幕,则控制范围
if (rect.width() >= width) {
if (rect.left > 0) {
deltaX = -rect.left;
}
if (rect.right = height) {
if (rect.top > 0) {
deltaY = -rect.top;
}
if (rect.bottom width || dh > height) {
scale = Math.min(width * 1.0f / dw, height * 1.0f / dh);
}
initScale = scale;
mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);
mScaleMatrix.postScale(scale, scale, getWidth() / 2,
getHeight() / 2);
// 图片移动至屏幕中心
setImageMatrix(mScaleMatrix);
once = false;
}
}
}
在onGlobalLayout的回调中,根据图片的宽和高以及屏幕的宽和高,对图片进行缩放以及移动至屏幕的中心。如果图片很小,那就正常显示
重写onTouchEvent方法,将触碰事件交给GestureDetector和ScaleGestureDetector处理
创建ScaleGestureDetector对象,在onScale的回调中对图片进行缩放的控制,首先进行缩放范围的判断,然后设置mScaleMatrix的scale值
但现在还存在一些问题:
1、缩放的中心点,我们设置是固定的,只在屏幕中间
2、放大后,无法移动图片
下面就解决这些问题
设置缩放中心
1、单纯的设置缩放中心
仅仅是设置中心很简单,直接在onScale中修改下中心点 :
mScaleMatrix.postScale(scaleFactor, scaleFactor,
detector.getFocusX(), detector.getFocusX());
setImageMatrix(mScaleMatrix);
但是,随意的中心点放大、缩小,会导致图片的位置的变化,最终导致,图片宽高大于屏幕时,图片与屏幕间出现白边;图片小于屏幕,但是不居中。
2、控制缩放时图片显示的范围
所以我们在缩放的时候需要手动控制下范围:
private void checkBorder() {
RectF rect = getMatrixRectF();
float deltaX = 0;
float deltaY = 0;
int width = getWidth();
int height = getHeight();
// 如果宽或高大于屏幕,则控制范围
if (rect.width() >= width) {
if (rect.left > 0) {
deltaX = -rect.left;
}
服务器托管网
if (rect.right = height) {
if (rect.top > 0) {
deltaY = -rect.top;
}
if (rect.bottom
现在图片缩放的功能就实现了
源代码
参考:
http://www.360doc.com/content/14/0610/21/16623487_385518125.shtml
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
print(2^2) –4 print(3^4) –27 — 等于pow(3, 4) cmd交互 通过 lua -i proj 打开的文件, 可以用 dofiles “xx.lua” (文件在IDE编辑)重新载入, 热更? lua -e …