实现技术主要用到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. CSS 宝典

    input点击时候,有个灰块 outline:medium; -webkit-tap-highlight-color:rgba(0,0,0,0); -webkit-user-modify:read-w ...

  2. hrbrid需要做的

    1 返回并刷新 A webveiw push 到 B webview.当由B返回到A时候, A需要刷新页面.

  3. Salesforce 数据清洗

    新系统上线后,需要导入历史数据,但是旧数据格式,数据缺失,数据错误,奇异值,属性归类与新系统有很大的gap.因此我们需要建立一套数据动态清洗规则给Salesforce系统,通过这些规则自动清洗导入数据 ...

  4. Scorpio-CSharp总链接

    简介 源码目录介绍

  5. 在MFC中,使用控制台Console输出调试信息

    1.在MFC的应用类的InitInstance()函数里添加: AllocConsole(); 有时候需要调整这行代码在InitInstance函数的位置 2.继续添加以下代码 freopen(&qu ...

  6. oracle的over函数应用(转载)

    摘自: http://www.poluoluo.com/jzxy/201004/81921.html 百度文库也记载了Oracle中over()分析函数的用法 在泡坛子的时候中无意中发现了这个函数,才 ...

  7. /proc/net/tcp中各项参数说明

    /proc/net/tcp中的内容由tcp4_seq_show()函数打印,该函数中有三种打印形式,我们这里这只列出状态是TCP_SEQ_STATE_LISTENING或TCP_SEQ_STATE_E ...

  8. JS定时程序,设定一个一直刷新,又时间间隔的js,读取当前的时间并显示

    <!doctype html><html><head><meta charset="utf-8"><title>无标题文 ...

  9. AIX 环境下ODM库同步

    IBM AIX v5.3操作系统环境下有时会出现ODM库与rootvg硬盘上数据不同步的情况.使用命令lsvg -l datavg检查文件系统类型,发现显示为"???"这就表示OD ...

  10. 关于adb shell getprop相关

    adb shell : getprop 查看机器的全部信息参数 getprop ro.serialno 查看机器的序列号 getprop ro.carrier 查看机器的CID号 getprop ro ...