实现技术主要用到1、多点触摸  2、matrix的矩阵,平移、缩放

根据手指的数量判断是进行的拖动、还是缩放动作

package com.bi.xintest;

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.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 = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); 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.mipmap.ic_launcher);
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 (float)Math.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];
} }

自定义View(三)实现简单的可拖动、可缩放的ImageView的更多相关文章

  1. 自定义View(三)--实现一个简单地流式布局

    Android中的流式布局也就是常说的瀑布流很是常见,不仅在很多项目中都能见到,而且面试中也有很多面试官问道,那么什么是流式布局呢?简单来说就是如果当前行的剩余宽度不足以摆放下一个控件的时候,则自动将 ...

  2. 自定义View其实很简单系列1-12

    作者: AigeStudio  http://blog.csdn.net/aigestudio 说明:文中的1/12表示12篇中的第1篇, 1/6=2/12表示12篇中的第2篇,其它类似. 自定义控件 ...

  3. Android 自定义View (三) 圆环交替 等待效果

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24500107 一个朋友今天有这么个需求(下图),我觉得那自定义View来做还是很 ...

  4. 自定义View(三),仿支付宝芝麻信用自定义控件

    仿支付宝的芝麻信用仪表盘 实现的效果 实现的功能: 指针和数字动态改变 背景动态变化 没了... 代码如下 MyCustomView.java package com.example.testcust ...

  5. 自定义View实现图片的绘制、旋转、缩放

    1.图片 把一张JPG图片改名为image.jpg,然后拷贝到项目的res-drawable中. 2.activity_main.xml <LinearLayout xmlns:android= ...

  6. Android自定义View之上拉、下拉列表 头部元素跟随 缩放、平移效果的实现

    滑动ListView列表然后 listView上边的视图 跟随着上拉或者下拉的距离 自动放大或者缩小  视图里边元素自动平移的效果 思路很简单 根据listView 的滑动距离去计算图片和文字应该平移 ...

  7. [转]Android自定义控件三部曲系列完全解析(动画, 绘图, 自定义View)

    来源:http://blog.csdn.net/harvic880925/article/details/50995268 一.自定义控件三部曲之动画篇 1.<自定义控件三部曲之动画篇(一)—— ...

  8. Android自定义View(一、初体验自定义TextView)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51454685 本文出自:[openXu的博客] 目录: 继承View重写onDraw方法 自 ...

  9. wing带你玩转自定义view系列(2) 简单模仿qq未读消息去除效果

    上一篇介绍了贝塞尔曲线的简单应用 仿360内存清理效果 这一篇带来一个  两条贝塞尔曲线的应用 : 仿qq未读消息去除效果. 转载请注明出处:http://blog.csdn.net/wingicho ...

  10. Android 自定义 view(三)—— onDraw 方法理解

    前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自 ...

随机推荐

  1. Android test---CTS

    转载 1.下载最新的CTS download 2.准备工作 3.启动CTS测试 3.1 在控制台进入目录android-cts,目录android-cts下有三个文件夹,其中一个是tools. 3.2 ...

  2. Drools规则

    1.实现业务逻辑和业务规则的分离,实现业务规则的集中管理 2.可以动态的改变业务规则,从而快速响应需求变更 3.业务分析人员也可以参与编辑.维护系统的业务规则 fact:一个普通的JavaBean插入 ...

  3. php学习笔记

    header("Content-Type:text/html;charset=utf-8");//设置中文请求中文 $host = "localhost";// ...

  4. 这是个简单的UTF8转码的小Demo

    NSString *name = @"你好啊"; NSString *string = [NSString stringWithFormat:@"%@",nam ...

  5. 利用npoi导出Excel

    npoi库是当下最流行的处理Excel.Word.PPT等Office文件格式 npoi的下载地址:http://npoi.codeplex.com/ npoi的官方学习地址: http://www. ...

  6. CentOS 6忘记密码解决办法,root和普通用户均可

    转自nui111的文章:http://blog.csdn.net/nui111/article/details/28007357 说明 操作系统:CentOS 6.0 遇到问题:忘记管理员账号root ...

  7. SpringMVC学习笔记(四)

    一.Controller接受网页参数. 1.使用方法的形参来接受 //使用基本类型和字符串来接受 @RequestMapping(value="/param2.do") publi ...

  8. fcitx jdk maven profile配置

    #小企鹅输入法配置 export GTK_IM_MODULE=fcitx export QT_IM_MODULE=fcitx export XMODIFIERS="@im=fcitx&quo ...

  9. RabbitMQ 入门指南(Java)

    RabbitMQ是一个受欢迎的消息代理,通常用于应用程序之间或者程序的不同组件之间通过消息来进行集成.本文简单介绍了如何使用 RabbitMQ,假定你已经配置好了rabbitmq服务器. Rabbit ...

  10. python基础知识4——collection类——计数器,有序字典,默认字典,可命名元组,双向队列

    1.计数器(counter) Counter是对字典类型的补充,用于追踪值的出现次数. ps:具备字典的所有功能 + 自己的功能  Counter 我们从中挑选一些相对常用的方法来举例: 在上面的例子 ...