`

android view的缩放平移简单实现

 
阅读更多
参考了下网上一些实现

主要是通过matrix实现的

用到的技术点:1,多点触摸
2,matrix的矩阵,平移和缩放


package com.nico;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class ScaleView extends ImageView {

	final public static int DRAG = 1;
	final public static int ZOOM = 2;

	public int mode = 0;

	private Matrix matrix = new Matrix();
	private Matrix matrix1 = new Matrix();
	private Matrix saveMatrix = new Matrix();

	private float x_down = 0;
	private float y_down = 0;

	private Bitmap touchImg;

	private PointF mid = new PointF();


	private float initDis = 1f;

	private int screenWidth, screenHeight;

	private float[] x = new float[4];
	private float[] y = new float[4];

	private boolean flag = false;

	public ScaleView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
	}

	public ScaleView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public ScaleView(Context context) {
		super(context);
		touchImg = BitmapFactory.decodeResource(getResources(), R.drawable.img);
		DisplayMetrics dm = getResources().getDisplayMetrics();
		screenWidth = dm.widthPixels;
		screenHeight = dm.heightPixels;
		matrix = new Matrix();
		// this.setScaleType(ScaleType.MATRIX);
	}

	@Override
	protected void onDraw(Canvas canvas) {

		canvas.save();
		// 根据 matrix 来重绘新的view
		canvas.drawBitmap(touchImg, matrix, null);
		canvas.restore();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		int action = event.getAction();
		// 多点触摸的时候 必须加上MotionEvent.ACTION_MASK
		switch (action & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			saveMatrix.set(matrix);
			x_down = event.getX();
			y_down = event.getY();
			// 初始为drag模式
			mode = DRAG;
			break;

		case MotionEvent.ACTION_POINTER_DOWN:
			saveMatrix.set(matrix);
			// 初始的两个触摸点间的距离
			initDis = spacing(event);
			// 设置为缩放模式
			mode = ZOOM;
			// 多点触摸的时候 计算出中间点的坐标
			midPoint(mid, event);
			break;

		case MotionEvent.ACTION_MOVE:

			// drag模式
			if (mode == DRAG) {
				// 设置当前的 matrix
				matrix1.set(saveMatrix);
				// 平移 当前坐标减去初始坐标 移动的距离
				matrix1.postTranslate(event.getX() - x_down, event.getY()
						- y_down);// 平移
				// 判断达到移动标准
				flag = checkMatrix(matrix1);
				if (flag) {
					// 设置matrix
					matrix.set(matrix1);

					// 调用ondraw重绘
					invalidate();
				}
			} else if (mode == ZOOM) {
				matrix1.set(saveMatrix);
				float newDis = spacing(event);
				// 计算出缩放比例
				float scale = newDis / initDis;

				// 以mid为中心进行缩放
				matrix1.postScale(scale, scale, mid.x, mid.y);
				flag = checkMatrix(matrix1);
				if (flag) {
					matrix.set(matrix1);
					invalidate();
				}
			}
			break;

		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_POINTER_UP:
			mode = 0;
			break;
		}

		return true;

	}

	//取两点的距离
	private float spacing(MotionEvent event) {
		try {
			float x = event.getX(0) - event.getX(1);
			float y = event.getY(0) - event.getY(1);
			return FloatMath.sqrt(x * x + y * y);
		} catch (IllegalArgumentException ex) {
			Log.v("TAG", ex.getLocalizedMessage());
			return 0;
		}
	}

	//取两点的中点
	private void midPoint(PointF point, MotionEvent event) {
		try {
			float x = event.getX(0) + event.getX(1);
			float y = event.getY(0) + event.getY(1);
			point.set(x / 2, y / 2);
		} catch (IllegalArgumentException ex) {

			//这个异常是android自带的,网上清一色的这么说。。。。
			Log.v("TAG", ex.getLocalizedMessage());
		}
	}

	private boolean checkMatrix(Matrix m) {

		GetFour(m);

		// 出界判断  
		//view的右边缘x坐标小于屏幕宽度的1/3的时候,
		// view左边缘大于屏幕款短的2/3的时候
		//view的下边缘在屏幕1/3上的时候
		//view的上边缘在屏幕2/3下的时候
		if ((x[0] < screenWidth / 3 && x[1] < screenWidth / 3
				&& x[2] < screenWidth / 3 && x[3] < screenWidth / 3)
				|| (x[0] > screenWidth * 2 / 3 && x[1] > screenWidth * 2 / 3
						&& x[2] > screenWidth * 2 / 3 && x[3] > screenWidth * 2 / 3)
						|| (y[0] < screenHeight / 3 && y[1] < screenHeight / 3
								&& y[2] < screenHeight / 3 && y[3] < screenHeight / 3)
								|| (y[0] > screenHeight * 2 / 3 && y[1] > screenHeight * 2 / 3
										&& y[2] > screenHeight * 2 / 3 && y[3] > screenHeight * 2 / 3)) {
			return true;
		}
		// 图片现宽度
		double width = Math.sqrt((x[0] - x[1]) * (x[0] - x[1]) + (y[0] - y[1])
				* (y[0] - y[1]));
		// 缩放比率判断 宽度打雨3倍屏宽,或者小于1/3屏宽
		if (width < screenWidth / 3 || width > screenWidth * 3) {
			return true;
		}
		return false;

		// if ((x[0] >= 0 && x[1] >= 0 && x[2] >= 0 && x[3] >= 0)
		// && (x[0] <= screenWidth && x[1] <= screenWidth
		// && x[2] <= screenWidth && x[3] <= screenWidth)
		// && (y[0] >= 0 && y[1] >= 0 && y[2] >= 0 && y[3] >= 0) && (y[0] <=
		// screenHeight
		// && y[1] <= screenHeight && y[2] <= screenHeight && y[3] <=
		// screenHeight)) {
		//
		// return true;
		// }
		//
		// return false;
	}

	private void GetFour(Matrix matrix) {
		float[] f = new float[9];
		matrix.getValues(f);
//		StringBuffer sb = new StringBuffer();
//		for(float ff : f)
//		{
//			sb.append(ff+"  ");
//		}
		// 图片4个顶点的坐标
		//矩阵  9     MSCALE_X 缩放的, MSKEW_X 倾斜的    。MTRANS_X 平移的 
		x[0] = f[Matrix.MSCALE_X] * 0 + f[Matrix.MSKEW_X] * 0
				+ f[Matrix.MTRANS_X];
		y[0] = f[Matrix.MSKEW_Y] * 0 + f[Matrix.MSCALE_Y] * 0
				+ f[Matrix.MTRANS_Y];
		x[1] = f[Matrix.MSCALE_X] * touchImg.getWidth() + f[Matrix.MSKEW_X] * 0
				+ f[Matrix.MTRANS_X];
		y[1] = f[Matrix.MSKEW_Y] * touchImg.getWidth() + f[Matrix.MSCALE_Y] * 0
				+ f[Matrix.MTRANS_Y];
		x[2] = f[Matrix.MSCALE_X] * 0 + f[Matrix.MSKEW_X]
				* touchImg.getHeight() + f[Matrix.MTRANS_X];
		y[2] = f[Matrix.MSKEW_Y] * 0 + f[Matrix.MSCALE_Y]
				* touchImg.getHeight() + f[Matrix.MTRANS_Y];
		x[3] = f[Matrix.MSCALE_X] * touchImg.getWidth() + f[Matrix.MSKEW_X]
				* touchImg.getHeight() + f[Matrix.MTRANS_X];
		y[3] = f[Matrix.MSKEW_Y] * touchImg.getWidth() + f[Matrix.MSCALE_Y]
				* touchImg.getHeight() + f[Matrix.MTRANS_Y];
	}

}

分享到:
评论
1 楼 usedlie 2016-06-17  
if (flag) { 
matrix.set(matrix1); 
invalidate(); 
}

这个逻辑反了,private boolean checkMatrix(Matrix m)这个方法是越界判断,假如越界,则返回true;


谢谢博主的GetFour(Matrix matrix)这个方法,正愁找不到缩放后的图片的坐标呢。。
一开始还以为得记录用户的一切操作(比如偏移量,缩放什么的),帮了大忙,谢谢;

虽说网上不少缩放、移动的控件,不过还是这种自定义的才能满足各种蛋疼的需求;

下一步看看要不要优化中心点=。=

相关推荐

    android手势处理图片平移、缩放和旋转

    总的来说,"android手势处理图片平移、缩放和旋转"涵盖了Android手势检测、自定义View、图片操作等多个核心知识点,是Android开发中的一个典型应用场景。通过熟练掌握这些技术,开发者可以为用户提供更加丰富和直观...

    Android缩放平移的时间刻度尺

    "Android缩放平移的时间刻度尺"项目提供了一个可扩展的解决方案,帮助开发者实现类似功能。下面将详细阐述这个组件的关键知识点。 1. **自定义View**: 时间刻度尺本质上是一个自定义的Android View,通过继承自`...

    安卓绘图 canvas 绘图 平移缩放

    下面是一个简单的示例,展示如何使用Canvas进行平移和缩放操作: ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 保存当前状态 canvas.save(); // 平移 canvas....

    旋转缩放平移控件完美版.rar

    标题提到的"旋转缩放平移控件完美版.rar"提供了一个解决方案,允许用户通过触摸屏幕进行单指平移、单双指旋转和缩放的操作。 首先,我们来看看核心文件`MoveLayout.java`。这个文件很可能定义了一个自定义布局,...

    Android-一个可以实现单指移动双击缩放双指缩放的View

    在这个场景中,我们关注的是一个名为"RikkaScalableView"的自定义View,它实现了三个核心功能:单指移动、双击缩放以及双指缩放。这些功能对于构建交互丰富的应用,特别是图片查看器或地图应用,非常实用。 首先,...

    【原创】Android自定义View实现图片显示并能缩放、拖拽、切换

    为了支持平移,我们需要记录图片的中心点和当前的缩放比例。 3. **手势检测**: `ScaleGestureDetector`提供了`onScale()`和`onScaleBegin()`/`onScaleEnd()`回调,我们可以在这些回调中更新缩放比例,并相应地调整...

    安卓图片的多点缩放,平移,双击缩放

    在安卓开发中,实现图片的多点触控缩放、平移以及双击缩放功能是常见的需求,尤其是在设计交互式应用或者图像编辑类应用时。这个案例"安卓图片的多点缩放,平移,双击缩放"提供了一个自定义的ImageView组件,它允许...

    Android中实现图片平移、缩放、旋转同步进行 源码

    在Android开发中,图片操作是常见的功能之一,其中包括图片的平移、缩放和旋转。这篇博客分享的源码提供了一种实现这些操作同步进行的方法。以下是对这个知识点的详细解释。 首先,我们要理解Android中处理图像的...

    Android动画(平移,缩放,旋转,透明)

    本文将深入探讨Android中的四大基本动画类型:平移(Translation)、缩放(Scale)、旋转(Rotation)和透明度变化(Alpha)。我们将详细了解这些动画的工作原理,以及如何在代码中实现它们。 首先,我们来讨论平移...

    Android canvas 放大 缩小 平移

    Android的Matrix类提供了对2D变换的支持,包括缩放(scale)、平移(translate)和旋转(rotate)。要实现放大和缩小,我们可以创建一个Matrix对象,然后调用其setScale()方法,传入缩放的X轴和Y轴因子。例如,要将...

    Android 补间动画,具体介绍了透明度、平移,旋转,缩放4种动画效果的实现,简单易懂

    在本教程中,我们将深入探讨如何实现透明度、平移、旋转和缩放这四种基本的Android补间动画。 1. **透明度动画**(Alpha Animation):透明度动画主要通过调整视图的alpha值来改变其可见度。例如,可以设置一个按钮...

    Android-一个Android图片缩放查看控件支持手势

    Android的`Matrix`类可以用来改变图像的坐标系统,实现缩放和平移。在处理手势时,开发者会更新Matrix对象,然后将其应用到Bitmap上,从而改变图片的显示大小。 4. **平移功能** 平移操作与缩放类似,也是通过调整...

    android基础动画平移,缩放,透明渐变,滚动

    本文将详细讲解Android基础动画中的平移、缩放、透明渐变和滚动这四种基本动作。 首先,我们来看**平移(Translation)**动画。在Android中,可以通过`TranslateAnimation`类来实现对象的移动。这个类允许你设置动画...

    Android单点平移多点缩放旋转Demo

    在Android开发中,实现平移、缩放和旋转功能通常涉及到手势识别和视图变换,这对于构建具有丰富交互性的用户界面至关重要。这个"Android单点平移多点缩放旋转Demo"是一个很好的学习资源,它展示了如何在一个View上...

    Android SurfaceView 实现图片缩放 滑动

    可以使用Matrix来控制图片的平移、缩放和旋转。 ```java Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_image); Matrix matrix = new Matrix(); canvas.drawBitmap(bitmap, ...

    Android 自定义缩放控件

    通过自定义,我们可以增加手势识别,实现平移和缩放的交互效果,提升图片查看的体验。 在实现自定义缩放控件时,我们需要考虑以下几个关键点: 1. **手势识别**:首先,我们需要集成Android的手势库(如...

    Android 手势检测实战 打造支持缩放平移的图片预览效果【VewPager版】

    本教程将深入探讨如何利用Android的手势检测机制,特别是`ScaleGestureDetector`,结合`ViewPager`来打造一个支持缩放和平移的图片预览效果。 `ScaleGestureDetector`是Android SDK提供的一种工具类,它可以帮助...

    Android View 跟随手势移动和缩放

    "Android View 跟随手势移动和缩放"的主题聚焦于如何实现View在屏幕上跟随用户的触摸手势进行平移(translate)和缩放(zoom)操作。这种功能广泛应用于图片查看器、地图应用以及各种需要用户自定义布局的场景。 ...

    手势控制旋转、平移、缩放

    在Android开发中,手势控制是用户交互的重要组成部分,特别是在图像视图(ImageView)上实现手势操作,如旋转、平移和缩放,可以极大地提升用户体验。`TouchImageView` 是一个自定义视图,它扩展了Android原生的`...

Global site tag (gtag.js) - Google Analytics