今天我们来编写一个缩放效果的ImageView ,网上有很多人都讲了这些。但有许多人都直接使用了库文件,
那么我们今天做的是直接上代码编写一个拖动和缩放的ImageView,具体看效果图
那么简单了分析一下。在手机上缩放图片和拖动要用到什么?手指对不对
那么控件上什么事件和手机有关。View.OnTouchListener 对不对。
ok,那么先新建一个Class
···
public class BaseDragZoomImageView extends ImageView implements View.OnTouchListener
···
没错,继承ImageView 并且添加View.OnTouchListener事件
然后我们看看构造函数
public BaseDragZoomImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
setOnTouchListener(this);
}
public BaseDragZoomImageView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
setOnTouchListener(this);
}
public BaseDragZoomImageView(Context context)
{
this(context, null);
setOnTouchListener(this);
}
对,在构造函数中,我们将setOnTouchListener 设置了。
那么这个setOnTouchListener 具体怎么做。我们就先分析一下onTouch 中MotionEvent。
我们都知道手指的操作有很多,那么Andorid自然也将这种情况分了很多种case。
- MotionEvent.ACTION_DOWN 手指按下屏幕
- MotionEvent.ACTION_MOVE 手指在屏幕上移动
- MotionEvent.ACTION_UP 手指离开屏幕
- MotionEvent.ACTION_POINTER_UP 当触点离开屏幕,但是屏幕上还有触点(手指)
- MotionEvent.ACTION_POINTER_DOWN 当屏幕上已经有触点(手指),再有一个触点压下屏幕
很显然,这些看起来好像都能够用得到。
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 手指压下屏幕
case MotionEvent.ACTION_DOWN:
mode = MODE_DRAG;
// 记录ImageView当前的移动位置
currentMatrix.set(getImageMatrix());
startPoint.set(event.getX(), event.getY());
break;
// 手指在屏幕上移动,改事件会被不断触发
case MotionEvent.ACTION_MOVE:
// 拖拉图片
if (mode == MODE_DRAG) {
float dx = event.getX() - startPoint.x; // 得到x轴的移动距离
float dy = event.getY() - startPoint.y; // 得到x轴的移动距离
// 在没有移动之前的位置上进行移动
matrix.set(currentMatrix);
matrix.postTranslate(dx, dy);
}
// 放大缩小图片
else if (mode == MODE_ZOOM) {
float endDis = distance(event);// 结束距离
if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10
float scale = endDis / startDis;// 得到缩放倍数
matrix.set(currentMatrix);
matrix.postScale(scale, scale,midPoint.x,midPoint.y);
}
}
break;
// 手指离开屏幕
case MotionEvent.ACTION_UP:
// 当触点离开屏幕,但是屏幕上还有触点(手指)
case MotionEvent.ACTION_POINTER_UP:
mode = 0;
break;
// 当屏幕上已经有触点(手指),再有一个触点压下屏幕
case MotionEvent.ACTION_POINTER_DOWN:
mode = MODE_ZOOM;
startDis = distance(event);
if (startDis > 10f) { // 两个手指并拢在一起的时候像素大于10
midPoint = mid(event);
//记录当前ImageView的缩放倍数
currentMatrix.set(getImageMatrix());
}
break;
}
setImageMatrix(matrix);
return true;
}
ok,收工。具体就只有这么多。我们来看下整个class
package com.jonkming.easyui.image.dragzoom.ui;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.util.FloatMath;
public class BaseDragZoomImageView extends ImageView implements View.OnTouchListener{
private int mode = 0;// 初始状态
private static final int MODE_DRAG = 1;
private static final int MODE_ZOOM = 2;
private PointF startPoint = new PointF();
private Matrix matrix = new Matrix();
private Matrix currentMatrix = new Matrix();
private float startDis;
private PointF midPoint;
public BaseDragZoomImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
setOnTouchListener(this);
}
public BaseDragZoomImageView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
setOnTouchListener(this);
}
public BaseDragZoomImageView(Context context)
{
this(context, null);
setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 手指压下屏幕
case MotionEvent.ACTION_DOWN:
mode = MODE_DRAG;
// 记录ImageView当前的移动位置
currentMatrix.set(getImageMatrix());
startPoint.set(event.getX(), event.getY());
break;
// 手指在屏幕上移动,改事件会被不断触发
case MotionEvent.ACTION_MOVE:
// 拖拉图片
if (mode == MODE_DRAG) {
float dx = event.getX() - startPoint.x; // 得到x轴的移动距离
float dy = event.getY() - startPoint.y; // 得到x轴的移动距离
// 在没有移动之前的位置上进行移动
matrix.set(currentMatrix);
matrix.postTranslate(dx, dy);
}
// 放大缩小图片
else if (mode == MODE_ZOOM) {
float endDis = distance(event);// 结束距离
if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10
float scale = endDis / startDis;// 得到缩放倍数
matrix.set(currentMatrix);
matrix.postScale(scale, scale,midPoint.x,midPoint.y);
}
}
break;
// 手指离开屏幕
case MotionEvent.ACTION_UP:
// 当触点离开屏幕,但是屏幕上还有触点(手指)
case MotionEvent.ACTION_POINTER_UP:
mode = 0;
break;
// 当屏幕上已经有触点(手指),再有一个触点压下屏幕
case MotionEvent.ACTION_POINTER_DOWN:
mode = MODE_ZOOM;
startDis = distance(event);
if (startDis > 10f) { // 两个手指并拢在一起的时候像素大于10
midPoint = mid(event);
//记录当前ImageView的缩放倍数
currentMatrix.set(getImageMatrix());
}
break;
}
setImageMatrix(matrix);
return true;
}
private float distance(MotionEvent event) {
float dx = event.getX(1) - event.getX(0);
float dy = event.getY(1) - event.getY(0);
return (float) Math.sqrt(dx * dx + dy * dy);
}
private PointF mid(MotionEvent event) {
float midX = (event.getX(1) + event.getX(0)) / 2;
float midY = (event.getY(1) + event.getY(0)) / 2;
return new PointF(midX, midY);
}
}
然后看布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.jonkming.easyui.image.dragzoom.ui.BaseDragZoomImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/dragandzoombase"
android:scaleType="matrix"
/>
</LinearLayout>
就是这么简单。
代码所在位置: GitHub
您可能感兴趣的文章:android 添加随意拖动的桌面悬浮窗口Android 仿淘宝、京东商品详情页向上拖动查看图文详情控件DEMO详解Android 可拖动的seekbar自定义进度值Android编程之控件可拖动的实现方法android 应用内部悬浮可拖动按钮简单实现代码Android编程实现图标拖动效果的方法Android实现跟随手指拖动并自动贴边的View样式(实例demo)android Matrix实现图片随意放大缩小或拖动Android自定义View实现拖动选择按钮Android使用ViewDragHelper实现QQ聊天气泡拖动效果